module Data.RangeMin.Fusion.Stream.Monadic (
Stream (..),
length,
iunfoldMN,
imapM,
imapM_,
generateM,
snocM,
ifoldlM,
imapAccumLM,
fromListN) where
import Prelude hiding (replicate, map, length, sequence_)
import Data.RangeMin.Common.Types
import Data.RangeMin.Common.Combinators
data Stream m a = forall s . Stream (Index -> s -> m (Step s a)) s !Length
data Step s a = Done | Last a | Yield a s
length :: Stream m a -> Length
length (Stream _ _ n) = n
iunfoldMN :: Monad m => Length -> (Index -> b -> m (Maybe (a, b))) -> b -> Stream m a
iunfoldMN !n f s0 = Stream suc s0 n where
suc i s = do
unf <- f i s
case unf of
Nothing -> return Done
Just (a, s') -> return (Yield a s')
imapM :: Monad m => (Index -> a -> m b) -> Stream m a -> Stream m b
imapM f (Stream suc s0 n) = Stream suc' s0 n where
suc' i s = do
step <- suc i s
case step of
Done -> return Done
Last a -> Last `liftM` f i a
Yield a s' -> do
b <- f i a
return (Yield b s')
imapM_ :: Monad m => (Index -> a -> m b) -> Stream m a -> m ()
imapM_ f str = sequence_ (imapM f str)
generateM :: Monad m => Length -> (Index -> m a) -> Stream m a
generateM n f = Stream suc () n where
suc i _ = if i < n then do
x <- f i
return (Yield x ())
else return Done
sequence_ :: Monad m => Stream m a -> m ()
sequence_ (Stream suc s0 _) = go 0 s0 where
go !i s = do
step <- suc i s
case step of
Yield _ s' -> go (i+1) s'
_ -> return ()
snocM :: Monad m => Stream m a -> m a -> Stream m a
Stream suc s0 n `snocM` z = Stream suc' s0 (n+1) where
suc' i s = if i < n then suc i s else Last `liftM` z
ifoldlM :: Monad m => (b -> Index -> a -> m b) -> b -> Stream m a -> m b
ifoldlM f z0 (Stream suc s0 _) = go 0 s0 z0 where
go !i s z = do
step <- suc i s
case step of
Done -> return z
Last a -> f z i a
Yield a s' -> go (i+1) s' =<< f z i a
imapAccumLM :: Monad m => (b -> Index -> a -> m (c, b)) -> b -> Stream m a -> Stream m c
imapAccumLM f z0 (Stream suc s0 n) = Stream suc' (s0, z0) n where
suc' i (s, z) = do
step <- suc i s
case step of
Done -> return Done
Last a -> (Last . fst) `liftM` f z i a
Yield a s' -> do
(y, z') <- f z i a
return (Yield y (s', z'))
fromListN :: Monad m => Length -> [a] -> Stream m a
fromListN n xs = Stream suc xs n where
suc _ (x:xs) = return (Yield x xs)
suc _ [] = return Done