{-# LANGUAGE Arrows #-}
{-# LANGUAGE Rank2Types #-}
module Data.MonadicStreamFunction.Util where
import Control.Arrow
import Control.Category
import Control.Monad
import Control.Monad.Base
import Data.Monoid
import Data.MonadicStreamFunction.Core
import Data.MonadicStreamFunction.Instances.ArrowChoice ()
import Data.VectorSpace
import Prelude hiding (id, (.))
import Control.Monad.Trans.MSF.State
type MStream m a = MSF m () a
type MSink m a = MSF m a ()
mapMaybeS :: Monad m => MSF m a b -> MSF m (Maybe a) (Maybe b)
mapMaybeS msf = proc maybeA -> case maybeA of
Just a -> arr Just <<< msf -< a
Nothing -> returnA -< Nothing
withSideEffect :: Monad m => (a -> m b) -> MSF m a a
withSideEffect method = (id &&& arrM method) >>> arr fst
withSideEffect_ :: Monad m => m b -> MSF m a a
withSideEffect_ method = withSideEffect $ const method
iPre :: Monad m
=> a
-> MSF m a a
iPre firsta = feedback firsta $ arr swap
where swap (a,b) = (b, a)
iPost :: Monad m => b -> MSF m a b -> MSF m a b
iPost b sf = sf >>> (feedback (Just b) $ arr $ \(c, ac) -> case ac of
Nothing -> (c, Nothing)
Just b' -> (b', Nothing))
next :: Monad m => b -> MSF m a b -> MSF m a b
next b sf = sf >>> iPre b
fifo :: Monad m => MSF m [a] (Maybe a)
fifo = feedback [] $ proc (as, accum) -> do
let accum' = accum ++ as
returnA -< case accum' of
[] -> (Nothing, [])
(a : as) -> (Just a , as)
count :: (Num n, Monad m) => MSF m a n
count = arr (const 1) >>> accumulateWith (+) 0
sumS :: (RModule v, Monad m) => MSF m v v
sumS = sumFrom zeroVector
sumFrom :: (RModule v, Monad m) => v -> MSF m v v
sumFrom = accumulateWith (^+^)
mappendS :: (Monoid n, Monad m) => MSF m n n
mappendS = mappendFrom mempty
{-# INLINE mappendS #-}
mappendFrom :: (Monoid n, Monad m) => n -> MSF m n n
mappendFrom = accumulateWith mappend
accumulateWith :: Monad m => (a -> s -> s) -> s -> MSF m a s
accumulateWith f s0 = feedback s0 $ arr g
where
g (a, s) = let s' = f a s in (s', s')
mealy :: Monad m => (a -> s -> (b, s)) -> s -> MSF m a b
mealy f s0 = feedback s0 $ arr $ uncurry f
unfold :: Monad m => (a -> (b, a)) -> a -> MSF m () b
unfold f a = feedback a (arr (snd >>> f))
repeatedly :: Monad m => (a -> a) -> a -> MSF m () a
repeatedly f = unfold $ f >>> dup
where
dup a = (a, a)
trace :: Show a => String -> MSF IO a a
trace = traceWith putStrLn
traceWith :: (Monad m, Show a) => (String -> m ()) -> String -> MSF m a a
traceWith method msg =
withSideEffect (method . (msg ++) . show)
traceWhen :: (Monad m, Show a) => (a -> Bool) -> (String -> m ()) -> String -> MSF m a a
traceWhen cond method msg = withSideEffect $ \a ->
when (cond a) $ method $ msg ++ show a
pauseOn :: Show a => (a -> Bool) -> String -> MSF IO a a
pauseOn cond = traceWhen cond $ \s -> print s >> getLine >> return ()