on master help sign in
Refactor/rename/add basic unfold constructors
0954511Harendra Kumar
benchmark/Streamly/Benchmark/Data/Unfold.hs+9−9
@@ -181,13 +181,13 @@ consM :: Monad m => Int -> Int -> m ()
181consM size start =
181consM size start =
182 drainTransformationDefault (size + start) (UF.consM return) start
182 drainTransformationDefault (size + start) (UF.consM return) start
183
183
184−{-# INLINE _singletonM #-}
184+{-# INLINE _functionM #-}
185−_singletonM :: Monad m => Int -> Int -> m ()
185+_functionM :: Monad m => Int -> Int -> m ()
186−_singletonM _ start = drainGeneration (UF.singletonM return) start
186+_functionM _ start = drainGeneration (UF.functionM return) start
187
187
188−{-# INLINE _singleton #-}
188+{-# INLINE _function #-}
189−_singleton :: Monad m => Int -> Int -> m ()
189+_function :: Monad m => Int -> Int -> m ()
190−_singleton _ start = drainGeneration (UF.singleton id) start
190+_function _ start = drainGeneration (UF.function id) start
191
191
192{-# INLINE _identity #-}
192{-# INLINE _identity #-}
193_identity :: Monad m => Int -> Int -> m ()
193_identity :: Monad m => Int -> Int -> m ()
@@ -626,8 +626,8 @@ o_1_space_generation size =
626 -- Very small benchmarks, reporting in ns
626 -- Very small benchmarks, reporting in ns
627 -- , benchIO "nilM" $ nilM size
627 -- , benchIO "nilM" $ nilM size
628 , benchIO "consM" $ consM size
628 , benchIO "consM" $ consM size
629− -- , benchIO "singletonM" $ singletonM size
629+ -- , benchIO "functionM" $ functionM size
630− -- , benchIO "singleton" $ singleton size
630+ -- , benchIO "function" $ function size
631 -- , benchIO "identity" $ identity size
631 -- , benchIO "identity" $ identity size
632 -- , benchIO "const" $ const size
632 -- , benchIO "const" $ const size
633 , benchIO "unfoldrM" $ unfoldrM size
633 , benchIO "unfoldrM" $ unfoldrM size
@@ -736,7 +736,7 @@ inspect $ hasNoTypeClasses 'readWriteOnExceptionUnfold
736readWriteHandleExceptionUnfold :: Handle -> Handle -> IO ()
736readWriteHandleExceptionUnfold :: Handle -> Handle -> IO ()
737readWriteHandleExceptionUnfold inh devNull =
737readWriteHandleExceptionUnfold inh devNull =
738 let handler (_e :: SomeException) = hClose inh >> return 10
738 let handler (_e :: SomeException) = hClose inh >> return 10
739− readEx = UF.handle (UF.singletonM handler) FH.read
739+ readEx = UF.handle (UF.functionM handler) FH.read
740 in SP.fold (FH.write devNull) $ SP.unfold readEx inh
740 in SP.fold (FH.write devNull) $ SP.unfold readEx inh
741
741
742#ifdef INSPECTION
742#ifdef INSPECTION
src/Streamly/Data/Unfold.hs+5−1
@@ -63,9 +63,13 @@ module Streamly.Data.Unfold
63 -- One to one correspondence with
63 -- One to one correspondence with
64 -- "Streamly.Internal.Data.Stream.IsStream.Generate"
64 -- "Streamly.Internal.Data.Stream.IsStream.Generate"
65
65
66+ -- ** Basic Constructors
67+ , unfoldrM
68+ , function
69+ , functionM
70+
66 -- ** Generators
71 -- ** Generators
67 -- | Generate a monadic stream from a seed.
72 -- | Generate a monadic stream from a seed.
68− , unfoldrM
69 , repeatM
73 , repeatM
70 , replicateM
74 , replicateM
71 , iterateM
75 , iterateM
src/Streamly/Internal/Data/Unfold.hs+11−24
@@ -85,18 +85,22 @@ module Streamly.Internal.Data.Unfold
85 -- * Unfolds
85 -- * Unfolds
86 -- One to one correspondence with
86 -- One to one correspondence with
87 -- "Streamly.Internal.Data.Stream.IsStream.Generate"
87 -- "Streamly.Internal.Data.Stream.IsStream.Generate"
88− -- ** Primitives
88+ -- ** Basic Constructors
89− , singletonM
89+ , mkUnfoldM
90− , singleton
90+ , mkUnfoldrM
91+ , unfoldrM
92+ , functionM
93+ , function
91 , identity
94 , identity
92− , yieldM
93− , yield
94 , nilM
95 , nilM
95 , consM
96 , consM
96
97
98+ -- ** From Values
99+ , yieldM
100+ , yield
101+
97 -- ** Generators
102 -- ** Generators
98 -- | Generate a monadic stream from a seed.
103 -- | Generate a monadic stream from a seed.
99− , unfoldrM
100 , repeatM
104 , repeatM
101 , replicateM
105 , replicateM
102 , fromIndicesM
106 , fromIndicesM
@@ -224,7 +228,7 @@ import Prelude
224-- | Map an action on the input argument of the 'Unfold'.
228-- | Map an action on the input argument of the 'Unfold'.
225--
229--
226-- @
230-- @
227−-- lmapM f = Unfold.many (Unfold.singletonM f)
231+-- lmapM f = Unfold.many (Unfold.functionM f)
228-- @
232-- @
229--
233--
230-- /Pre-release/
234-- /Pre-release/
@@ -468,23 +472,6 @@ fromListM = Unfold step inject
468 step (x:xs) = x >>= \r -> return $ Yield r xs
472 step (x:xs) = x >>= \r -> return $ Yield r xs
469 step [] = return Stop
473 step [] = return Stop
470
474
471−-- | Build a stream by unfolding a /monadic/ step function starting from a seed.
472−-- The step function returns the next element in the stream and the next seed
473−-- value. When it is done it returns 'Nothing' and the stream ends.
474−--
475−-- /Pre-release/
476−--
477−{-# INLINE unfoldrM #-}
478−unfoldrM :: Monad m => (a -> m (Maybe (b, a))) -> Unfold m a b
479−unfoldrM next = Unfold step return
480− where
481− {-# INLINE_LATE step #-}
482− step st = do
483− r <- next st
484− return $ case r of
485− Just (x, s) -> Yield x s
486− Nothing -> Stop
487−
488------------------------------------------------------------------------------
475------------------------------------------------------------------------------
489-- Specialized Generation
476-- Specialized Generation
490------------------------------------------------------------------------------
477------------------------------------------------------------------------------
src/Streamly/Internal/Data/Unfold/Type.hs+82−23
@@ -9,10 +9,15 @@
9module Streamly.Internal.Data.Unfold.Type
9module Streamly.Internal.Data.Unfold.Type
10 ( Unfold (..)
10 ( Unfold (..)
11
11
12− -- * From values
12+ -- * Basic Constructors
13− , singletonM
13+ , mkUnfoldM
14− , singleton
14+ , mkUnfoldrM
15+ , unfoldrM
16+ , functionM
17+ , function
15 , identity
18 , identity
19+
20+ -- * From Values
16 , yieldM
21 , yieldM
17 , yield
22 , yield
18
23
@@ -73,10 +78,54 @@ data Unfold m a b =
73 -- | @Unfold step inject@
78 -- | @Unfold step inject@
74 forall s. Unfold (s -> m (Step s b)) (a -> m s)
79 forall s. Unfold (s -> m (Step s b)) (a -> m s)
75
80
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+
76-- | Map a function on the input argument of the 'Unfold'.
125-- | Map a function on the input argument of the 'Unfold'.
77--
126--
78-- @
127-- @
79−-- lmap f = Unfold.many (Unfold.singleton f)
128+-- lmap f = Unfold.many (Unfold.function f)
80-- @
129-- @
81--
130--
82-- /Pre-release/
131-- /Pre-release/
@@ -109,9 +158,10 @@ instance Functor m => Functor (Unfold m a) where
109-- Applicative
158-- Applicative
110------------------------------------------------------------------------------
159------------------------------------------------------------------------------
111
160
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
113-- supplied monadic action.
162-- supplied monadic action.
114--
163--
164+-- /Pre-release/
115{-# INLINE yieldM #-}
165{-# INLINE yieldM #-}
116yieldM :: Applicative m => m b -> Unfold m a b
166yieldM :: Applicative m => m b -> Unfold m a b
117yieldM m = Unfold step inject
167yieldM m = Unfold step inject
@@ -124,6 +174,10 @@ yieldM m = Unfold step inject
124 step True = pure Stop
174 step True = pure Stop
125
175
126-- | Discards the unfold input and always returns the argument of 'yield'.
176-- | Discards the unfold input and always returns the argument of 'yield'.
177+--
178+-- > yield = yieldM . pure
179+--
180+-- /Pre-release/
127yield :: Applicative m => b -> Unfold m a b
181yield :: Applicative m => b -> Unfold m a b
128yield = yieldM Prelude.. pure
182yield = yieldM Prelude.. pure
129
183
@@ -314,36 +368,41 @@ instance Monad m => Monad (Unfold m a) where
314-- Category
368-- Category
315-------------------------------------------------------------------------------
369-------------------------------------------------------------------------------
316
370
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.
318--
373--
319−{-# INLINE singletonM #-}
374+-- /Pre-release/
375+{-# INLINE functionM #-}
320−singletonM :: Monad m => (a -> m b) -> Unfold m a b
376+functionM :: Applicative m => (a -> m b) -> Unfold m a b
321−singletonM f = Unfold step inject
377+functionM f = Unfold step inject
322
378
323 where
379 where
324
380
325− inject x = return $ Just x
381+ inject x = pure $ Just x
326
382
327 {-# INLINE_LATE step #-}
383 {-# INLINE_LATE step #-}
328− step (Just x) = f x >>= \r -> return $ Yield r Nothing
384+ step (Just x) = (`Yield` Nothing) <$> f x
329− step Nothing = return Stop
385+ step Nothing = pure Stop
330
386
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.
332--
389--
333−-- > singleton f = singletonM $ return . f
390+-- > function f = functionM $ return . f
334--
391--
392+-- /Pre-release/
335−{-# INLINE singleton #-}
393+{-# INLINE function #-}
336−singleton :: Monad m => (a -> b) -> Unfold m a b
394+function :: Applicative m => (a -> b) -> Unfold m a b
337−singleton f = singletonM $ return Prelude.. f
395+function f = functionM $ pure Prelude.. f
338
396
339−-- | Identity unfold. Generates a singleton stream with the seed as the only
397+-- | Identity unfold. The unfold generates a singleton stream having the input
340−-- element in the stream.
398+-- as the only element.
341--
399--
342−-- > identity = singleton Prelude.id
400+-- > identity = function Prelude.id
343--
401--
402+-- /Pre-release/
344{-# INLINE identity #-}
403{-# INLINE identity #-}
345−identity :: Monad m => Unfold m a a
404+identity :: Applicative m => Unfold m a a
346−identity = singleton Prelude.id
405+identity = function Prelude.id
347
406
348{-# ANN type ConcatState Fuse #-}
407{-# ANN type ConcatState Fuse #-}
349data ConcatState s1 s2 = ConcatOuter s1 | ConcatInner s1 s2
408data ConcatState s1 s2 = ConcatOuter s1 | ConcatInner s1 s2
@@ -468,7 +527,7 @@ zipWith f = zipWithM (\a b -> return (f a b))
468{-# ANN module "HLint: ignore Use zip" #-}
527{-# ANN module "HLint: ignore Use zip" #-}
469instance Monad m => Arrow (Unfold m) where
528instance Monad m => Arrow (Unfold m) where
470 {-# INLINE arr #-}
529 {-# INLINE arr #-}
471− arr = singleton
530+ arr = function
472
531
473 {-# INLINE (***) #-}
532 {-# INLINE (***) #-}
474 u1 *** u2 = zipWith (,) (lmap fst u1) (lmap snd u2)
533 u1 *** u2 = zipWith (,) (lmap fst u1) (lmap snd u2)
test/Streamly/Test/Data/Unfold.hs+12−12
@@ -67,37 +67,37 @@ testUnfoldD = testUnfold
67
67
68lmapM :: Bool
68lmapM :: Bool
69lmapM =
69lmapM =
70− let unf = UF.lmapM (\x -> modify (+ 1) >> return x) (UF.singleton id)
70+ let unf = UF.lmapM (\x -> modify (+ 1) >> return x) (UF.function id)
71 in testUnfoldMD unf 1 0 1 [1]
71 in testUnfoldMD unf 1 0 1 [1]
72
72
73supply :: Bool
73supply :: Bool
74supply =
74supply =
75− let unf = UF.supply 1 (UF.singleton id)
75+ let unf = UF.supply 1 (UF.function id)
76 in testUnfold unf undefined ([1] :: [Int])
76 in testUnfold unf undefined ([1] :: [Int])
77
77
78supplyFirst :: Bool
78supplyFirst :: Bool
79supplyFirst =
79supplyFirst =
80− let unf = UF.supplyFirst 1 (UF.singleton id)
80+ let unf = UF.supplyFirst 1 (UF.function id)
81 in testUnfold unf 2 ([(1, 2)] :: [(Int, Int)])
81 in testUnfold unf 2 ([(1, 2)] :: [(Int, Int)])
82
82
83supplySecond :: Bool
83supplySecond :: Bool
84supplySecond =
84supplySecond =
85− let unf = UF.supplySecond 1 (UF.singleton id)
85+ let unf = UF.supplySecond 1 (UF.function id)
86 in testUnfold unf 2 ([(2, 1)] :: [(Int, Int)])
86 in testUnfold unf 2 ([(2, 1)] :: [(Int, Int)])
87
87
88discardFirst :: Bool
88discardFirst :: Bool
89discardFirst =
89discardFirst =
90− let unf = UF.discardFirst (UF.singleton id)
90+ let unf = UF.discardFirst (UF.function id)
91 in testUnfold unf ((1, 2) :: (Int, Int)) [2]
91 in testUnfold unf ((1, 2) :: (Int, Int)) [2]
92
92
93discardSecond :: Bool
93discardSecond :: Bool
94discardSecond =
94discardSecond =
95− let unf = UF.discardSecond (UF.singleton id)
95+ let unf = UF.discardSecond (UF.function id)
96 in testUnfold unf ((1, 2) :: (Int, Int)) [1]
96 in testUnfold unf ((1, 2) :: (Int, Int)) [1]
97
97
98swap :: Bool
98swap :: Bool
99swap =
99swap =
100− let unf = UF.swap (UF.singleton id)
100+ let unf = UF.swap (UF.function id)
101 in testUnfold unf ((1, 2) :: (Int, Int)) [(2, 1)]
101 in testUnfold unf ((1, 2) :: (Int, Int)) [(2, 1)]
102
102
103-------------------------------------------------------------------------------
103-------------------------------------------------------------------------------
@@ -134,9 +134,9 @@ consM =
134 unf = cns $ cns $ UF.nilM $ \a -> modify (+ a)
134 unf = cns $ cns $ UF.nilM $ \a -> modify (+ a)
135 in testUnfoldMD unf 1 0 3 [1, 2]
135 in testUnfoldMD unf 1 0 3 [1, 2]
136
136
137−singletonM :: Bool
137+functionM :: Bool
138−singletonM =
138+functionM =
139− let unf = UF.singletonM (\a -> modify (+ a) >> get)
139+ let unf = UF.functionM (\a -> modify (+ a) >> get)
140 in testUnfoldMD unf 1 0 1 [1]
140 in testUnfoldMD unf 1 0 1 [1]
141
141
142const :: Bool
142const :: Bool
@@ -378,8 +378,8 @@ testGeneration =
378 prop "fromStreamD" fromStreamD
378 prop "fromStreamD" fromStreamD
379 prop "nilM" nilM
379 prop "nilM" nilM
380 prop "consM" consM
380 prop "consM" consM
381− prop "singletonM" singletonM
381+ prop "functionM" functionM
382− -- prop "singleton" singleton
382+ -- prop "function" function
383 -- prop "identity" identity
383 -- prop "identity" identity
384 prop "const" const
384 prop "const" const
385 prop "unfoldrM" unfoldrM
385 prop "unfoldrM" unfoldrM