Use Applicative instead of Monad where possible

Only refactoring, no functional change.
In Unfold, StreamD and StreamK.
Also fix a few hlint issues.
This commit is contained in:
Harendra Kumar 2021-09-26 08:50:48 +05:30
parent ed2c32f99a
commit d28e2313f1
4 changed files with 172 additions and 179 deletions

View File

@ -3,7 +3,6 @@ src/Streamly/Internal/Data/Stream/PreludeCommon.hs
src/Streamly/Internal/Data/Stream/Serial.hs src/Streamly/Internal/Data/Stream/Serial.hs
src/Streamly/Internal/Data/Stream/Zip.hs src/Streamly/Internal/Data/Stream/Zip.hs
src/Streamly/Internal/Data/Stream/StreamK/Type.hs src/Streamly/Internal/Data/Stream/StreamK/Type.hs
src/Streamly/Internal/Data/Stream/StreamD/Type.hs
src/Streamly/Internal/Data/Pipe/Type.hs src/Streamly/Internal/Data/Pipe/Type.hs
src/Streamly/Internal/Data/SmallArray/Type.hs src/Streamly/Internal/Data/SmallArray/Type.hs
src/Streamly/Internal/Unicode/Stream.hs src/Streamly/Internal/Unicode/Stream.hs

View File

@ -92,6 +92,7 @@ import Control.Applicative (liftA2)
import Control.Monad (when) import Control.Monad (when)
import Control.Monad.Catch (MonadThrow, throwM) import Control.Monad.Catch (MonadThrow, throwM)
import Control.Monad.Trans.Class (lift, MonadTrans) import Control.Monad.Trans.Class (lift, MonadTrans)
import Data.Functor (($>))
import Data.Functor.Identity (Identity(..)) import Data.Functor.Identity (Identity(..))
import Fusion.Plugin.Types (Fuse(..)) import Fusion.Plugin.Types (Fuse(..))
import GHC.Base (build) import GHC.Base (build)
@ -134,22 +135,22 @@ pattern Stream step state <- (unShare -> UnStream step state)
-- | An empty 'Stream' with a side effect. -- | An empty 'Stream' with a side effect.
{-# INLINE_NORMAL nilM #-} {-# INLINE_NORMAL nilM #-}
nilM :: Monad m => m b -> Stream m a nilM :: Applicative m => m b -> Stream m a
nilM m = Stream (\_ _ -> m >> return Stop) () nilM m = Stream (\_ _ -> m $> Stop) ()
{-# INLINE_NORMAL consM #-} {-# INLINE_NORMAL consM #-}
consM :: Monad m => m a -> Stream m a -> Stream m a consM :: Applicative m => m a -> Stream m a -> Stream m a
consM m (Stream step state) = Stream step1 Nothing consM m (Stream step state) = Stream step1 Nothing
where where
{-# INLINE_LATE step1 #-} {-# INLINE_LATE step1 #-}
step1 _ Nothing = m >>= \x -> return $ Yield x (Just state) step1 _ Nothing = (`Yield` Just state) <$> m
step1 gst (Just st) = do step1 gst (Just st) = do
r <- step gst st (\case
return $
case r of
Yield a s -> Yield a (Just s) Yield a s -> Yield a (Just s)
Skip s -> Skip (Just s) Skip s -> Skip (Just s)
Stop -> Stop Stop -> Stop) <$> step gst st
-- | Does not fuse, has the same performance as the StreamK version. -- | Does not fuse, has the same performance as the StreamK version.
{-# INLINE_NORMAL uncons #-} {-# INLINE_NORMAL uncons #-}
@ -172,17 +173,18 @@ data UnfoldState s = UnfoldNothing | UnfoldJust s
-- | Convert an 'Unfold' into a 'Stream' by supplying it a seed. -- | Convert an 'Unfold' into a 'Stream' by supplying it a seed.
-- --
{-# INLINE_NORMAL unfold #-} {-# INLINE_NORMAL unfold #-}
unfold :: Monad m => Unfold m a b -> a -> Stream m b unfold :: Applicative m => Unfold m a b -> a -> Stream m b
unfold (Unfold ustep inject) seed = Stream step UnfoldNothing unfold (Unfold ustep inject) seed = Stream step UnfoldNothing
where
where
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step _ UnfoldNothing = inject seed >>= return . Skip . UnfoldJust step _ UnfoldNothing = Skip . UnfoldJust <$> inject seed
step _ (UnfoldJust st) = do step _ (UnfoldJust st) = do
r <- ustep st (\case
return $ case r of
Yield x s -> Yield x (UnfoldJust s) Yield x s -> Yield x (UnfoldJust s)
Skip s -> Skip (UnfoldJust s) Skip s -> Skip (UnfoldJust s)
Stop -> Stop Stop -> Stop) <$> ustep st
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- From Values -- From Values
@ -199,12 +201,14 @@ fromPure x = Stream (\_ s -> pure $ step undefined s) True
-- | Create a singleton 'Stream' from a monadic action. -- | Create a singleton 'Stream' from a monadic action.
{-# INLINE_NORMAL fromEffect #-} {-# INLINE_NORMAL fromEffect #-}
fromEffect :: Monad m => m a -> Stream m a fromEffect :: Applicative m => m a -> Stream m a
fromEffect m = Stream step True fromEffect m = Stream step True
where
where
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step _ True = m >>= \x -> return $ Yield x False step _ True = (`Yield` False) <$> m
step _ False = return Stop step _ False = pure Stop
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- From Containers -- From Containers
@ -226,13 +230,13 @@ fromList = Stream step
-- | Convert a CPS encoded StreamK to direct style step encoded StreamD -- | Convert a CPS encoded StreamK to direct style step encoded StreamD
{-# INLINE_LATE fromStreamK #-} {-# INLINE_LATE fromStreamK #-}
fromStreamK :: Monad m => K.Stream m a -> Stream m a fromStreamK :: Applicative m => K.Stream m a -> Stream m a
fromStreamK = Stream step fromStreamK = Stream step
where where
step gst m1 = step gst m1 =
let stop = return Stop let stop = pure Stop
single a = return $ Yield a K.nil single a = pure $ Yield a K.nil
yieldk a r = return $ Yield a r yieldk a r = pure $ Yield a r
in K.foldStreamShared gst yieldk single stop m1 in K.foldStreamShared gst yieldk single stop m1
-- | Convert a direct style step encoded StreamD to a CPS encoded StreamK -- | Convert a direct style step encoded StreamD to a CPS encoded StreamK
@ -261,7 +265,7 @@ toStreamK (Stream step state) = go state
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
{-# INLINE_NORMAL fold #-} {-# INLINE_NORMAL fold #-}
fold :: (Monad m) => Fold m a b -> Stream m a -> m b fold :: Monad m => Fold m a b -> Stream m a -> m b
fold fld strm = do fold fld strm = do
(b, _) <- fold_ fld strm (b, _) <- fold_ fld strm
return b return b
@ -349,7 +353,7 @@ foldrMx fstep final convert (Stream step state) = convert $ go SPEC state
-- --
{-# INLINE_NORMAL foldr #-} {-# INLINE_NORMAL foldr #-}
foldr :: Monad m => (a -> b -> b) -> b -> Stream m a -> m b foldr :: Monad m => (a -> b -> b) -> b -> Stream m a -> m b
foldr f z = foldrM (\a b -> liftA2 f (return a) b) (return z) foldr f z = foldrM (liftA2 f . return) (return z)
-- this performs horribly, should not be used -- this performs horribly, should not be used
{-# INLINE_NORMAL foldrS #-} {-# INLINE_NORMAL foldrS #-}
@ -409,8 +413,8 @@ foldlMx' fstep begin done (Stream step state) =
{-# INLINE foldlx' #-} {-# INLINE foldlx' #-}
foldlx' :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> m b foldlx' :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Stream m a -> m b
foldlx' fstep begin done m = foldlx' fstep begin done =
foldlMx' (\b a -> return (fstep b a)) (return begin) (return . done) m foldlMx' (\b a -> return (fstep b a)) (return begin) (return . done)
-- Adapted from the vector package. -- Adapted from the vector package.
-- XXX implement in terms of foldlMx'? -- XXX implement in terms of foldlMx'?
@ -576,17 +580,18 @@ instance Functor m => Functor (Stream m) where
-- Adapted from the vector package. -- Adapted from the vector package.
{-# INLINE_NORMAL take #-} {-# INLINE_NORMAL take #-}
take :: Monad m => Int -> Stream m a -> Stream m a take :: Applicative m => Int -> Stream m a -> Stream m a
take n (Stream step state) = n `seq` Stream step' (state, 0) take n (Stream step state) = n `seq` Stream step' (state, 0)
where
where
{-# INLINE_LATE step' #-} {-# INLINE_LATE step' #-}
step' gst (st, i) | i < n = do step' gst (st, i) | i < n = do
r <- step gst st (\case
return $ case r of
Yield x s -> Yield x (s, i + 1) Yield x s -> Yield x (s, i + 1)
Skip s -> Skip (s, i) Skip s -> Skip (s, i)
Stop -> Stop Stop -> Stop) <$> step gst st
step' _ (_, _) = return Stop step' _ (_, _) = pure Stop
-- Adapted from the vector package. -- Adapted from the vector package.
{-# INLINE_NORMAL takeWhileM #-} {-# INLINE_NORMAL takeWhileM #-}
@ -613,17 +618,20 @@ takeWhile f = takeWhileM (return . f)
{-# INLINE_NORMAL concatAp #-} {-# INLINE_NORMAL concatAp #-}
concatAp :: Functor f => Stream f (a -> b) -> Stream f a -> Stream f b concatAp :: Functor f => Stream f (a -> b) -> Stream f a -> Stream f b
concatAp (Stream stepa statea) (Stream stepb stateb) = Stream step' (Left statea) concatAp (Stream stepa statea) (Stream stepb stateb) =
where Stream step' (Left statea)
where
{-# INLINE_LATE step' #-} {-# INLINE_LATE step' #-}
step' gst (Left st) = fmap step' gst (Left st) = fmap
(\r -> case r of (\case
Yield f s -> Skip (Right (f, s, stateb)) Yield f s -> Skip (Right (f, s, stateb))
Skip s -> Skip (Left s) Skip s -> Skip (Left s)
Stop -> Stop) Stop -> Stop)
(stepa (adaptState gst) st) (stepa (adaptState gst) st)
step' gst (Right (f, os, st)) = fmap step' gst (Right (f, os, st)) = fmap
(\r -> case r of (\case
Yield a s -> Yield (f a) (Right (f, os, s)) Yield a s -> Yield (f a) (Right (f, os, s))
Skip s -> Skip (Right (f,os, s)) Skip s -> Skip (Right (f,os, s))
Stop -> Skip (Left os)) Stop -> Skip (Left os))
@ -639,19 +647,17 @@ apSequence (Stream stepa statea) (Stream stepb stateb) =
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step gst (Left st) = step gst (Left st) =
fmap fmap
(\r -> (\case
case r of Yield _ s -> Skip (Right (s, stateb))
Yield _ s -> Skip (Right (s, stateb)) Skip s -> Skip (Left s)
Skip s -> Skip (Left s) Stop -> Stop)
Stop -> Stop)
(stepa (adaptState gst) st) (stepa (adaptState gst) st)
step gst (Right (ostate, st)) = step gst (Right (ostate, st)) =
fmap fmap
(\r -> (\case
case r of Yield b s -> Yield b (Right (ostate, s))
Yield b s -> Yield b (Right (ostate, s)) Skip s -> Skip (Right (ostate, s))
Skip s -> Skip (Right (ostate, s)) Stop -> Skip (Left ostate))
Stop -> Skip (Left ostate))
(stepb gst st) (stepb gst st)
{-# INLINE_NORMAL apDiscardSnd #-} {-# INLINE_NORMAL apDiscardSnd #-}
@ -664,19 +670,17 @@ apDiscardSnd (Stream stepa statea) (Stream stepb stateb) =
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step gst (Left st) = step gst (Left st) =
fmap fmap
(\r -> (\case
case r of Yield b s -> Skip (Right (s, stateb, b))
Yield b s -> Skip (Right (s, stateb, b)) Skip s -> Skip (Left s)
Skip s -> Skip (Left s) Stop -> Stop)
Stop -> Stop)
(stepa gst st) (stepa gst st)
step gst (Right (ostate, st, b)) = step gst (Right (ostate, st, b)) =
fmap fmap
(\r -> (\case
case r of Yield _ s -> Yield b (Right (ostate, s, b))
Yield _ s -> Yield b (Right (ostate, s, b)) Skip s -> Skip (Right (ostate, s, b))
Skip s -> Skip (Right (ostate, s, b)) Stop -> Skip (Left ostate))
Stop -> Skip (Left ostate))
(stepb (adaptState gst) st) (stepb (adaptState gst) st)
instance Applicative f => Applicative (Stream f) where instance Applicative f => Applicative (Stream f) where
@ -728,7 +732,7 @@ unfoldMany (Unfold istep inject) (Stream ostep ost) =
i <- inject a i <- inject a
i `seq` return (Skip (ConcatMapUInner o' i)) i `seq` return (Skip (ConcatMapUInner o' i))
Skip o' -> return $ Skip (ConcatMapUOuter o') Skip o' -> return $ Skip (ConcatMapUOuter o')
Stop -> return $ Stop Stop -> return Stop
step _ (ConcatMapUInner o i) = do step _ (ConcatMapUInner o i) = do
r <- istep i r <- istep i

View File

@ -179,7 +179,7 @@ fromYieldK k = mkStream $ \_ _ sng _ -> k sng
-- | Add a yield function at the head of the stream. -- | Add a yield function at the head of the stream.
consK :: YieldK m a -> Stream m a -> Stream m a consK :: YieldK m a -> Stream m a -> Stream m a
consK k r = mkStream $ \_ yld _ _ -> k (\x -> yld x r) consK k r = mkStream $ \_ yld _ _ -> k (`yld` r)
-- XXX Build a stream from a repeating callback function. -- XXX Build a stream from a repeating callback function.
@ -241,8 +241,8 @@ nil = mkStream $ \_ _ _ stp -> stp
-- --
-- /Pre-release/ -- /Pre-release/
{-# INLINE_NORMAL nilM #-} {-# INLINE_NORMAL nilM #-}
nilM :: Monad m => m b -> Stream m a nilM :: Applicative m => m b -> Stream m a
nilM m = mkStream $ \_ _ _ stp -> m >> stp nilM m = mkStream $ \_ _ _ stp -> m *> stp
{-# INLINE_NORMAL fromPure #-} {-# INLINE_NORMAL fromPure #-}
fromPure :: a -> Stream m a fromPure :: a -> Stream m a
@ -259,8 +259,8 @@ infixr 5 `consM`
-- SPECIALIZE in the instance definition. -- SPECIALIZE in the instance definition.
{-# INLINE consM #-} {-# INLINE consM #-}
{-# SPECIALIZE consM :: IO a -> Stream IO a -> Stream IO a #-} {-# SPECIALIZE consM :: IO a -> Stream IO a -> Stream IO a #-}
consM :: (Monad m) => m a -> Stream m a -> Stream m a consM :: Monad m => m a -> Stream m a -> Stream m a
consM m r = MkStream $ \_ yld _ _ -> m >>= \a -> yld a r consM m r = MkStream $ \_ yld _ _ -> m >>= (`yld` r)
-- XXX specialize to IO? -- XXX specialize to IO?
{-# INLINE consMBy #-} {-# INLINE consMBy #-}
@ -1270,30 +1270,29 @@ fromFoldableM = Prelude.foldr consM nil
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
{-# INLINE uncons #-} {-# INLINE uncons #-}
uncons :: Monad m => Stream m a -> m (Maybe (a, Stream m a)) uncons :: Applicative m => Stream m a -> m (Maybe (a, Stream m a))
uncons m = uncons m =
let stop = return Nothing let stop = pure Nothing
single a = return (Just (a, nil)) single a = pure (Just (a, nil))
yieldk a r = return (Just (a, r)) yieldk a r = pure (Just (a, r))
in foldStream defState yieldk single stop m in foldStream defState yieldk single stop m
{-# INLINE tail #-} {-# INLINE tail #-}
tail :: Monad m => Stream m a -> m (Maybe (Stream m a)) tail :: Applicative m => Stream m a -> m (Maybe (Stream m a))
tail = tail =
let stop = return Nothing let stop = pure Nothing
single _ = return $ Just nil single _ = pure $ Just nil
yieldk _ r = return $ Just r yieldk _ r = pure $ Just r
in foldStream defState yieldk single stop in foldStream defState yieldk single stop
{-# INLINE init #-} {-# INLINE init #-}
init :: Monad m => Stream m a -> m (Maybe (Stream m a)) init :: Applicative m => Stream m a -> m (Maybe (Stream m a))
init = go1 init = go1
where where
go1 m1 = do go1 m1 = do
r <- uncons m1 (\case
case r of Nothing -> Nothing
Nothing -> return Nothing Just (h, t) -> Just $ go h t) <$> uncons m1
Just (h, t) -> return . Just $ go h t
go p m1 = mkStream $ \_ yld sng stp -> go p m1 = mkStream $ \_ yld sng stp ->
let single _ = sng p let single _ = sng p
yieldk a x = yld p $ go a x yieldk a x = yld p $ go a x

View File

@ -250,6 +250,7 @@ import Control.Exception (Exception, mask_)
import Control.Monad.Catch (MonadCatch) import Control.Monad.Catch (MonadCatch)
import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad.Trans.Control (MonadBaseControl, liftBaseOp_) import Control.Monad.Trans.Control (MonadBaseControl, liftBaseOp_)
import Data.Functor (($>))
import GHC.Types (SPEC(..)) import GHC.Types (SPEC(..))
import Streamly.Internal.Control.Concurrent (MonadAsync) import Streamly.Internal.Control.Concurrent (MonadAsync)
import Streamly.Internal.Data.Fold.Type (Fold(..)) import Streamly.Internal.Data.Fold.Type (Fold(..))
@ -417,25 +418,20 @@ mapMWithInput f (Unfold ustep uinject) = Unfold step inject
-- --
-- /Internal/ -- /Internal/
{-# INLINE_NORMAL either #-} {-# INLINE_NORMAL either #-}
either :: Monad m => Unfold m a b -> Unfold m (Either a a) (Either b b) either :: Applicative m => Unfold m a b -> Unfold m (Either a a) (Either b b)
either (Unfold step1 inject1) = Unfold step inject either (Unfold step1 inject1) = Unfold step inject
where where
inject (Left a) = do inject (Left a) = (, Left) <$> inject1 a
r <- inject1 a inject (Right a) = (, Right) <$> inject1 a
return (r, Left)
inject (Right a) = do
r <- inject1 a
return (r, Right)
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step (st, f) = do step (st, f) = do
r <- step1 st (\case
return $ case r of
Yield x s -> Yield (f x) (s, f) Yield x s -> Yield (f x) (s, f)
Skip s -> Skip (s, f) Skip s -> Skip (s, f)
Stop -> Stop Stop -> Stop) <$> step1 st
-- See StreamD.scanlM' for implementing this. -- See StreamD.scanlM' for implementing this.
-- --
@ -452,30 +448,29 @@ scanlM' = undefined
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
{-# INLINE_NORMAL fromStreamD #-} {-# INLINE_NORMAL fromStreamD #-}
fromStreamD :: Monad m => Unfold m (Stream m a) a fromStreamD :: Applicative m => Unfold m (Stream m a) a
fromStreamD = Unfold step return fromStreamD = Unfold step pure
where where
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step (UnStream step1 state1) = do step (UnStream step1 state1) =
r <- step1 defState state1 (\case
return $ case r of
Yield x s -> Yield x (Stream step1 s) Yield x s -> Yield x (Stream step1 s)
Skip s -> Skip (Stream step1 s) Skip s -> Skip (Stream step1 s)
Stop -> Stop Stop -> Stop) <$> step1 defState state1
{-# INLINE_NORMAL fromStreamK #-} {-# INLINE_NORMAL fromStreamK #-}
fromStreamK :: Monad m => Unfold m (K.Stream m a) a fromStreamK :: Applicative m => Unfold m (K.Stream m a) a
fromStreamK = Unfold step return fromStreamK = Unfold step pure
where where
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step stream = do step stream = do
r <- K.uncons stream (\case
return $ case r of
Just (x, xs) -> Yield x xs Just (x, xs) -> Yield x xs
Nothing -> Stop Nothing -> Stop) <$> K.uncons stream
-- XXX Using Unfold.fromStreamD seems to be faster (using cross product test -- XXX Using Unfold.fromStreamD seems to be faster (using cross product test
-- case) than using fromStream even if it is implemented using fromStreamD. -- case) than using fromStream even if it is implemented using fromStreamD.
@ -486,7 +481,7 @@ fromStreamK = Unfold step return
-- /Since: 0.8.0/ -- /Since: 0.8.0/
-- --
{-# INLINE_NORMAL fromStream #-} {-# INLINE_NORMAL fromStream #-}
fromStream :: (IsStream t, Monad m) => Unfold m (t m a) a fromStream :: (IsStream t, Applicative m) => Unfold m (t m a) a
fromStream = lmap IsStream.toStream fromStreamK fromStream = lmap IsStream.toStream fromStreamK
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -497,59 +492,61 @@ fromStream = lmap IsStream.toStream fromStreamK
-- effect. -- effect.
-- --
{-# INLINE nilM #-} {-# INLINE nilM #-}
nilM :: Monad m => (a -> m c) -> Unfold m a b nilM :: Applicative m => (a -> m c) -> Unfold m a b
nilM f = Unfold step return nilM f = Unfold step pure
where where
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step x = f x >> return Stop step x = f x $> Stop
-- | Prepend a monadic single element generator function to an 'Unfold'. The -- | Prepend a monadic single element generator function to an 'Unfold'. The
-- same seed is used in the action as well as the unfold. -- same seed is used in the action as well as the unfold.
-- --
-- /Pre-release/ -- /Pre-release/
{-# INLINE_NORMAL consM #-} {-# INLINE_NORMAL consM #-}
consM :: Monad m => (a -> m b) -> Unfold m a b -> Unfold m a b consM :: Applicative m => (a -> m b) -> Unfold m a b -> Unfold m a b
consM action unf = Unfold step inject consM action unf = Unfold step inject
where where
inject = return . Left inject = pure . Left
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step (Left a) = step (Left a) = (`Yield` Right (D.unfold unf a)) <$> action a
action a >>= \r -> return $ Yield r (Right (D.unfold unf a))
step (Right (UnStream step1 st)) = do step (Right (UnStream step1 st)) = do
res <- step1 defState st (\case
case res of Yield x s -> Yield x (Right (Stream step1 s))
Yield x s -> return $ Yield x (Right (Stream step1 s)) Skip s -> Skip (Right (Stream step1 s))
Skip s -> return $ Skip (Right (Stream step1 s)) Stop -> Stop) <$> step1 defState st
Stop -> return Stop
-- | Convert a list of pure values to a 'Stream' -- | Convert a list of pure values to a 'Stream'
-- --
-- /Since: 0.8.0/ -- /Since: 0.8.0/
-- --
{-# INLINE_LATE fromList #-} {-# INLINE_LATE fromList #-}
fromList :: Monad m => Unfold m [a] a fromList :: Applicative m => Unfold m [a] a
fromList = Unfold step inject fromList = Unfold step pure
where
inject = return where
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step (x:xs) = return $ Yield x xs step (x:xs) = pure $ Yield x xs
step [] = return Stop step [] = pure Stop
-- | Convert a list of monadic values to a 'Stream' -- | Convert a list of monadic values to a 'Stream'
-- --
-- /Since: 0.8.0/ -- /Since: 0.8.0/
-- --
{-# INLINE_LATE fromListM #-} {-# INLINE_LATE fromListM #-}
fromListM :: Monad m => Unfold m [m a] a fromListM :: Applicative m => Unfold m [m a] a
fromListM = Unfold step inject fromListM = Unfold step pure
where
inject = return where
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step (x:xs) = x >>= \r -> return $ Yield r xs step (x:xs) = (`Yield` xs) <$> x
step [] = return Stop step [] = pure Stop
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- Specialized Generation -- Specialized Generation
@ -560,31 +557,31 @@ fromListM = Unfold step inject
-- /Since: 0.8.0/ -- /Since: 0.8.0/
-- --
{-# INLINE replicateM #-} {-# INLINE replicateM #-}
replicateM :: Monad m => Int -> Unfold m (m a) a replicateM :: Applicative m => Int -> Unfold m (m a) a
replicateM n = Unfold step inject replicateM n = Unfold step inject
where where
inject x = return (x, n) inject action = pure (action, n)
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step (x, i) = step (action, i) =
if i <= 0 if i <= 0
then return Stop then pure Stop
else do else (\x -> Yield x (action, i - 1)) <$> action
x1 <- x
return $ Yield x1 (x, i - 1)
-- | Generates an infinite stream repeating the seed. -- | Generates an infinite stream repeating the seed.
-- --
-- /Since: 0.8.0/ -- /Since: 0.8.0/
-- --
{-# INLINE repeatM #-} {-# INLINE repeatM #-}
repeatM :: Monad m => Unfold m (m a) a repeatM :: Applicative m => Unfold m (m a) a
repeatM = Unfold step return repeatM = Unfold step pure
where where
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step x = x >>= \x1 -> return $ Yield x1 x step action = (`Yield` action) <$> action
-- | Generates an infinite stream starting with the given seed and applying the -- | Generates an infinite stream starting with the given seed and applying the
-- given function repeatedly. -- given function repeatedly.
@ -592,13 +589,13 @@ repeatM = Unfold step return
-- /Since: 0.8.0/ -- /Since: 0.8.0/
-- --
{-# INLINE iterateM #-} {-# INLINE iterateM #-}
iterateM :: Monad m => (a -> m a) -> Unfold m (m a) a iterateM :: Applicative m => (a -> m a) -> Unfold m (m a) a
iterateM f = Unfold step id iterateM f = Unfold step id
where where
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step x = do step x = Yield x <$> f x
fx <- f x
return $ Yield x fx
-- | @fromIndicesM gen@ generates an infinite stream of values using @gen@ -- | @fromIndicesM gen@ generates an infinite stream of values using @gen@
-- starting from the seed. -- starting from the seed.
@ -610,13 +607,13 @@ iterateM f = Unfold step id
-- /Pre-release/ -- /Pre-release/
-- --
{-# INLINE_NORMAL fromIndicesM #-} {-# INLINE_NORMAL fromIndicesM #-}
fromIndicesM :: Monad m => (Int -> m a) -> Unfold m Int a fromIndicesM :: Applicative m => (Int -> m a) -> Unfold m Int a
fromIndicesM gen = Unfold step return fromIndicesM gen = Unfold step pure
where
where
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step i = do step i = (`Yield` (i + 1)) <$> gen i
x <- gen i
return $ Yield x (i + 1)
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Filtering -- Filtering
@ -630,20 +627,20 @@ fromIndicesM gen = Unfold step return
-- /Since: 0.8.0/ -- /Since: 0.8.0/
-- --
{-# INLINE_NORMAL take #-} {-# INLINE_NORMAL take #-}
take :: Monad m => Int -> Unfold m a b -> Unfold m a b take :: Applicative m => Int -> Unfold m a b -> Unfold m a b
take n (Unfold step1 inject1) = Unfold step inject take n (Unfold step1 inject1) = Unfold step inject
where
inject x = do where
s <- inject1 x
return (s, 0) inject x = (, 0) <$> inject1 x
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step (st, i) | i < n = do step (st, i) | i < n = do
r <- step1 st (\case
return $ case r of
Yield x s -> Yield x (s, i + 1) Yield x s -> Yield x (s, i + 1)
Skip s -> Skip (s, i) Skip s -> Skip (s, i)
Stop -> Stop Stop -> Stop) <$> step1 st
step (_, _) = return Stop step (_, _) = pure Stop
-- | Same as 'filter' but with a monadic predicate. -- | Same as 'filter' but with a monadic predicate.
-- --
@ -676,31 +673,25 @@ filter f = filterM (return . f)
-- /Since: 0.8.0/ -- /Since: 0.8.0/
-- --
{-# INLINE_NORMAL drop #-} {-# INLINE_NORMAL drop #-}
drop :: Monad m => Int -> Unfold m a b -> Unfold m a b drop :: Applicative m => Int -> Unfold m a b -> Unfold m a b
drop n (Unfold step inject) = Unfold step' inject' drop n (Unfold step inject) = Unfold step' inject'
where where
inject' a = do inject' a = (, n) <$> inject a
b <- inject a
return (b, n)
{-# INLINE_LATE step' #-} {-# INLINE_LATE step' #-}
step' (st, i) step' (st, i)
| i > 0 = do | i > 0 = do
r <- step st (\case
return Yield _ s -> Skip (s, i - 1)
$ case r of Skip s -> Skip (s, i)
Yield _ s -> Skip (s, i - 1) Stop -> Stop) <$> step st
Skip s -> Skip (s, i)
Stop -> Stop
| otherwise = do | otherwise = do
r <- step st (\case
return Yield x s -> Yield x (s, 0)
$ case r of Skip s -> Skip (s, 0)
Yield x s -> Yield x (s, 0) Stop -> Stop) <$> step st
Skip s -> Skip (s, 0)
Stop -> Stop
-- | @dropWhileM f unf@ drops elements from the stream generated by @unf@ while -- | @dropWhileM f unf@ drops elements from the stream generated by @unf@ while
-- the condition holds true. The condition function @f@ is /monadic/ in nature. -- the condition holds true. The condition function @f@ is /monadic/ in nature.
@ -793,10 +784,10 @@ gbracket_ bef exc aft (Unfold estep einject) (Unfold step1 inject1) =
return $ Skip (Left r) return $ Skip (Left r)
step (Left st) = do step (Left st) = do
res <- estep st res <- estep st
case res of return $ case res of
Yield x s -> return $ Yield x (Left s) Yield x s -> Yield x (Left s)
Skip s -> return $ Skip (Left s) Skip s -> Skip (Left s)
Stop -> return Stop Stop -> Stop
-- | Run the alloc action @a -> m c@ with async exceptions disabled but keeping -- | Run the alloc action @a -> m c@ with async exceptions disabled but keeping
-- blocking operations interruptible (see 'Control.Exception.mask'). Use the -- blocking operations interruptible (see 'Control.Exception.mask'). Use the
@ -858,10 +849,10 @@ gbracket bef exc aft (Unfold estep einject) (Unfold step1 inject1) =
return $ Skip (Left r) return $ Skip (Left r)
step (Left st) = do step (Left st) = do
res <- estep st res <- estep st
case res of return $ case res of
Yield x s -> return $ Yield x (Left s) Yield x s -> Yield x (Left s)
Skip s -> return $ Skip (Left s) Skip s -> Skip (Left s)
Stop -> return Stop Stop -> Stop
-- | Run a side effect @a -> m c@ on the input @a@ before unfolding it using -- | Run a side effect @a -> m c@ on the input @a@ before unfolding it using
-- @Unfold m a b@. -- @Unfold m a b@.
@ -964,10 +955,10 @@ onException action (Unfold step1 inject1) = Unfold step inject
{-# INLINE_LATE step #-} {-# INLINE_LATE step #-}
step (st, v) = do step (st, v) = do
res <- step1 st `MC.onException` action v res <- step1 st `MC.onException` action v
case res of return $ case res of
Yield x s -> return $ Yield x (s, v) Yield x s -> Yield x (s, v)
Skip s -> return $ Skip (s, v) Skip s -> Skip (s, v)
Stop -> return Stop Stop -> Stop
{-# INLINE_NORMAL _finally #-} {-# INLINE_NORMAL _finally #-}
_finally :: MonadCatch m => (a -> m c) -> Unfold m a b -> Unfold m a b _finally :: MonadCatch m => (a -> m c) -> Unfold m a b -> Unfold m a b