@@ -9,10 +9,15 @@
99module Streamly.Internal.Data.Unfold.Type
1010 ( Unfold (..)
1111
12− -- * From values
13− , singletonM
14− , singleton
12+ -- * Basic Constructors
13+ , mkUnfoldM
14+ , mkUnfoldrM
15+ , unfoldrM
16+ , functionM
17+ , function
1518 , identity
19+
20+ -- * From Values
1621 , yieldM
1722 , yield
1823
@@ -73,10 +78,54 @@ data Unfold m a b =
7378 -- | @Unfold step inject@
7479 forall s. Unfold (s -> m (Step s b)) (a -> m s)
7580
81+------------------------------------------------------------------------------
82+-- Basic constructors
83+------------------------------------------------------------------------------
84+
85+-- | Make an unfold from @step@ and @inject@ functions.
86+--
87+-- /Pre-release/
88+{-# INLINE mkUnfoldM #-}
89+mkUnfoldM :: (s -> m (Step s b)) -> (a -> m s) -> Unfold m a b
90+mkUnfoldM = Unfold
91+
92+-- | Make an unfold from a step function.
93+--
94+-- See also: 'unfoldrM'
95+--
96+-- /Pre-release/
97+{-# INLINE mkUnfoldrM #-}
98+mkUnfoldrM :: Applicative m => (a -> m (Step a b)) -> Unfold m a b
99+mkUnfoldrM step = Unfold step pure
100+
101+-- The type 'Step' is isomorphic to 'Maybe'. Ideally unfoldrM should be the
102+-- same as mkUnfoldrM, this is for compatibility with traditional Maybe based
103+-- unfold step functions.
104+--
105+-- | Build a stream by unfolding a /monadic/ step function starting from a seed.
106+-- The step function returns the next element in the stream and the next seed
107+-- value. When it is done it returns 'Nothing' and the stream ends.
108+--
109+-- /Pre-release/
110+--
111+{-# INLINE unfoldrM #-}
112+unfoldrM :: Applicative m => (a -> m (Maybe (b, a))) -> Unfold m a b
113+unfoldrM next = Unfold step pure
114+ where
115+ {-# INLINE_LATE step #-}
116+ step st =
117+ (\case
118+ Just (x, s) -> Yield x s
119+ Nothing -> Stop) <$> next st
120+
121+------------------------------------------------------------------------------
122+-- Map input
123+------------------------------------------------------------------------------
124+
76125-- | Map a function on the input argument of the 'Unfold'.
77126--
78127-- @
79−-- lmap f = Unfold.many (Unfold.singleton f)
128+-- lmap f = Unfold.many (Unfold.function f)
80129-- @
81130--
82131-- /Pre-release/
@@ -109,9 +158,10 @@ instance Functor m => Functor (Unfold m a) where
109158-- Applicative
110159------------------------------------------------------------------------------
111160
112−-- | The unfold discards its input and generates a singleton stream using the
161+-- | The unfold discards its input and generates a function stream using the
113162-- supplied monadic action.
114163--
164+-- /Pre-release/
115165{-# INLINE yieldM #-}
116166yieldM :: Applicative m => m b -> Unfold m a b
117167yieldM m = Unfold step inject
@@ -124,6 +174,10 @@ yieldM m = Unfold step inject
124174 step True = pure Stop
125175
126176-- | Discards the unfold input and always returns the argument of 'yield'.
177+--
178+-- > yield = yieldM . pure
179+--
180+-- /Pre-release/
127181yield :: Applicative m => b -> Unfold m a b
128182yield = yieldM Prelude.. pure
129183
@@ -314,36 +368,41 @@ instance Monad m => Monad (Unfold m a) where
314368-- Category
315369-------------------------------------------------------------------------------
316370
317−-- | Lift a monadic function into an unfold generating a singleton stream.
371+-- | Lift a monadic function into an unfold. The unfold generates a singleton
372+-- stream.
318373--
319−{-# INLINE singletonM #-}
320−singletonM :: Monad m => (a -> m b) -> Unfold m a b
321−singletonM f = Unfold step inject
374+-- /Pre-release/
375+{-# INLINE functionM #-}
376+functionM :: Applicative m => (a -> m b) -> Unfold m a b
377+functionM f = Unfold step inject
322378
323379 where
324380
325− inject x = return $ Just x
381+ inject x = pure $ Just x
326382
327383 {-# INLINE_LATE step #-}
328− step (Just x) = f x >>= \r -> return $ Yield r Nothing
329− step Nothing = return Stop
384+ step (Just x) = (`Yield` Nothing) <$> f x
385+ step Nothing = pure Stop
330386
331−-- | Lift a pure function into an unfold generating a singleton stream.
387+-- | Lift a pure function into an unfold. The unfold generates a singleton
388+-- stream.
332389--
333−-- > singleton f = singletonM $ return . f
390+-- > function f = functionM $ return . f
334391--
335−{-# INLINE singleton #-}
336−singleton :: Monad m => (a -> b) -> Unfold m a b
337−singleton f = singletonM $ return Prelude.. f
392+-- /Pre-release/
393+{-# INLINE function #-}
394+function :: Applicative m => (a -> b) -> Unfold m a b
395+function f = functionM $ pure Prelude.. f
338396
339−-- | Identity unfold. Generates a singleton stream with the seed as the only
340−-- element in the stream.
397+-- | Identity unfold. The unfold generates a singleton stream having the input
398+-- as the only element.
341399--
342−-- > identity = singleton Prelude.id
400+-- > identity = function Prelude.id
343401--
402+-- /Pre-release/
344403{-# INLINE identity #-}
345−identity :: Monad m => Unfold m a a
346−identity = singleton Prelude.id
404+identity :: Applicative m => Unfold m a a
405+identity = function Prelude.id
347406
348407{-# ANN type ConcatState Fuse #-}
349408data ConcatState s1 s2 = ConcatOuter s1 | ConcatInner s1 s2
@@ -468,7 +527,7 @@ zipWith f = zipWithM (\a b -> return (f a b))
468527{-# ANN module "HLint: ignore Use zip" #-}
469528instance Monad m => Arrow (Unfold m) where
470529 {-# INLINE arr #-}
471− arr = singleton
530+ arr = function
472531
473532 {-# INLINE (***) #-}
474533 u1 *** u2 = zipWith (,) (lmap fst u1) (lmap snd u2)