-- | -- Copyright : (c) Ivan Perez and Manuel Baerenz, 2016 -- License : BSD3 -- Maintainer : ivan.perez@keera.co.uk -- -- This module contains operations on monadic streams that are asynchronous, -- i.e. that change the speed at which data enters or leaves the 'MSF'. module Data.MonadicStreamFunction.Async where -- Internal imports import Data.MonadicStreamFunction.InternalCore (MSF(MSF, unMSF)) import Data.MonadicStreamFunction.Util (MStream) -- | -- Concatenates a monadic stream of lists to a monadic stream. -- The stream of lists will be called exactly when new data is needed. -- -- Example: -- -- >>> let intstream = constS $ putStrLn "Enter a list of Ints:" >> readLn :: MStream IO [Int] -- >>> reactimate $ concatS intstream >>> arrM print -- Enter a list of Ints: -- [1, 2, 33] -- 1 -- 2 -- 33 -- Enter a list of Ints: -- [] -- Enter a list of Ints: -- [] -- Enter a list of Ints: -- [1, 2] -- 1 -- 2 -- Enter a list of Ints: -- ... -- -- Beware that @concatS msf@ becomes unproductive when @msf@ starts outputting -- empty lists forever. This is ok: -- -- >>> let boolToList b = if b then ["Yes"] else [] -- >>> let everyOddEmpty = count >>> arr (even >>> boolToList) -- >>> reactimate $ concatS everyOddEmpty >>> arrM print -- "Yes" -- "Yes" -- "Yes" -- "Yes" -- "Yes" -- ... -- -- But this will be caught in a loop: -- -- >>> let after3Empty = count >>> arr ((<= 3) >>> boolToList) -- >>> reactimate $ concatS after3Empty >>> arrM print -- "Yes" -- "Yes" -- "Yes" -- ^CInterrupted. concatS :: Monad m => MStream m [b] -> MStream m b concatS :: forall (m :: * -> *) b. Monad m => MStream m [b] -> MStream m b concatS MStream m [b] msf = forall (m :: * -> *) a b. (a -> m (b, MSF m a b)) -> MSF m a b MSF forall a b. (a -> b) -> a -> b $ \() _ -> forall {m :: * -> *} {a} {a}. Monad m => MSF m () [a] -> [a] -> m (a, MSF m a a) tick MStream m [b] msf [] where tick :: MSF m () [a] -> [a] -> m (a, MSF m a a) tick MSF m () [a] msf' (a b:[a] bs) = forall (m :: * -> *) a. Monad m => a -> m a return (a b, forall (m :: * -> *) a b. (a -> m (b, MSF m a b)) -> MSF m a b MSF forall a b. (a -> b) -> a -> b $ \a _ -> MSF m () [a] -> [a] -> m (a, MSF m a a) tick MSF m () [a] msf' [a] bs) tick MSF m () [a] msf' [] = do ([a] bs, MSF m () [a] msf'') <- forall (m :: * -> *) a b. MSF m a b -> a -> m (b, MSF m a b) unMSF MSF m () [a] msf' () MSF m () [a] -> [a] -> m (a, MSF m a a) tick MSF m () [a] msf'' [a] bs