on master help sign in
Change signature of enumerate functions
commitba9a4e8f6adb03bc8c02d482ea6293f88a33f9a8 authorRanjeet Kumar Ranjan <ranjeetr@composewell.com> dateFri 20 Aug 2021, 15:19 (5 years ago) parent00db551
7 files changed+747−287
benchmark/Streamly/Benchmark/Data/Unfold.hs+24−17 src/Streamly/Internal/Data/Unfold.hs+25−144 src/Streamly/Internal/Data/Unfold/Enumeration.hs+371−82 src/Streamly/Internal/Data/Unfold/Type.hs+35−1 streamly.cabal+1−2 test/Streamly/Test/Data/Unfold.hs+289−39 test/Streamly/Test/Prelude/Serial.hs+2−2
benchmark/Streamly/Benchmark/Data/Unfold.hs+24−17
@@ -54,7 +54,7 @@ benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f
5454-- generate numbers up to the argument value
5555{-# INLINE source #-}
5656source :: Monad m => Int -> Unfold m Int Int
57−source n = UF.enumerateFromToIntegral n
57+source n = UF.supplySecond n UF.enumerateFromToIntegral
5858
5959-------------------------------------------------------------------------------
6060-- Benchmark helpers
@@ -73,7 +73,7 @@ drainTransformation unf f seed = drainGeneration (f unf) seed
7373drainTransformationDefault ::
7474 Monad m => Int -> (Unfold m Int Int -> Unfold m c d) -> c -> m ()
7575drainTransformationDefault to =
76− drainTransformation (UF.enumerateFromToIntegral to)
76+ drainTransformation (UF.supplySecond to UF.enumerateFromToIntegral)
7777
7878{-# INLINE drainProduct #-}
7979drainProduct ::
@@ -96,7 +96,7 @@ drainProductDefault to = drainProduct src src
9696
9797 where
9898
99− src = UF.enumerateFromToIntegral to
99+ src = UF.supplySecond to UF.enumerateFromToIntegral
100100
101101-------------------------------------------------------------------------------
102102-- Operations on input
@@ -122,7 +122,7 @@ supply size start =
122122supplyFirst :: Monad m => Int -> Int -> m ()
123123supplyFirst size start =
124124 drainTransformation
125− (UF.take size UF.enumerateFromStepIntegral)
125+ (UF.take size UF.enumerateFromThenIntegral)
126126 (UF.supplyFirst start)
127127 1
128128
@@ -130,7 +130,7 @@ supplyFirst size start =
130130supplySecond :: Monad m => Int -> Int -> m ()
131131supplySecond size start =
132132 drainTransformation
133− (UF.take size UF.enumerateFromStepIntegral)
133+ (UF.take size UF.enumerateFromThenIntegral)
134134 (UF.supplySecond 1)
135135 start
136136
@@ -148,7 +148,7 @@ discardSecond size start =
148148swap :: Monad m => Int -> Int -> m ()
149149swap size start =
150150 drainTransformation
151− (UF.take size UF.enumerateFromStepIntegral)
151+ (UF.take size UF.enumerateFromThenIntegral)
152152 UF.swap
153153 (1, start)
154154
@@ -245,15 +245,19 @@ fromIndicesM :: Monad m => Int -> Int -> m ()
245245fromIndicesM size start =
246246 drainGeneration (UF.take size (UF.fromIndicesM return)) start
247247
248−{-# INLINE enumerateFromStepIntegral #-}
249−enumerateFromStepIntegral :: Monad m => Int -> Int -> m ()
250−enumerateFromStepIntegral size start =
251− drainGeneration (UF.take size UF.enumerateFromStepIntegral) (start, 1)
248+{-# INLINE enumerateFromThenIntegral #-}
249+enumerateFromThenIntegral :: Monad m => Int -> Int -> m ()
250+enumerateFromThenIntegral size start =
251+ drainGeneration (UF.take size UF.enumerateFromThenIntegral) (start, 1)
252252
253253{-# INLINE enumerateFromToIntegral #-}
254254enumerateFromToIntegral :: Monad m => Int -> Int -> m ()
255255enumerateFromToIntegral size start =
256− drainGeneration (UF.enumerateFromToIntegral (size + start)) start
256+ drainGeneration
257+ ( UF.supplySecond
258+ (size + start)
259+ UF.enumerateFromToIntegral
260+ ) start
257261
258262{-# INLINE enumerateFromIntegral #-}
259263enumerateFromIntegral :: Monad m => Int -> Int -> m ()
@@ -263,18 +267,21 @@ enumerateFromIntegral size start =
263267{-# INLINE enumerateFromStepNum #-}
264268enumerateFromStepNum :: Monad m => Int -> Int -> m ()
265269enumerateFromStepNum size start =
266− drainGeneration (UF.take size (UF.enumerateFromStepNum 1)) start
270+ drainGeneration (UF.take size (UF.enumerateFromThenNum)) (start, 1)
267271
268272{-# INLINE numFrom #-}
269273numFrom :: Monad m => Int -> Int -> m ()
270−numFrom size start = drainGeneration (UF.take size UF.numFrom) start
274+numFrom size start = drainGeneration (UF.take size UF.enumerateFromNum) start
271275
272276{-# INLINE enumerateFromToFractional #-}
273277enumerateFromToFractional :: Monad m => Int -> Int -> m ()
274278enumerateFromToFractional size start =
275279 let intToDouble x = (fromInteger (fromIntegral x)) :: Double
276280 in drainGeneration
277− (UF.enumerateFromToFractional (intToDouble $ start + size))
281+ ( UF.supplySecond
282+ (intToDouble $ start + size)
283+ UF.enumerateFromToFractional
284+ )
278285 (intToDouble start)
279286
280287-------------------------------------------------------------------------------
@@ -434,8 +441,8 @@ concatMapM value start =
434441 where
435442
436443 val = nthRoot 2 value
437− unfoldInGen i = return (UF.enumerateFromToIntegral (i + val))
438− unfoldOut = UF.enumerateFromToIntegral (start + val)
444+ unfoldInGen i = return (UF.supplySecond (i + val) UF.enumerateFromToIntegral)
445+ unfoldOut = UF.supplySecond (start + val) UF.enumerateFromToIntegral
439446
440447{-# INLINE toNull #-}
441448toNull :: Monad m => Int -> Int -> m ()
@@ -638,7 +645,7 @@ o_1_space_generation size =
638645 , benchIO "repeatM" $ repeatM size
639646 , benchIO "iterateM" $ iterateM size
640647 , benchIO "fromIndicesM" $ fromIndicesM size
641− , benchIO "enumerateFromStepIntegral" $ enumerateFromStepIntegral size
648+ , benchIO "enumerateFromThenIntegral" $ enumerateFromThenIntegral size
642649 , benchIO "enumerateFromToIntegral" $ enumerateFromToIntegral size
643650 , benchIO "enumerateFromIntegral" $ enumerateFromIntegral size
644651 , benchIO "enumerateFromStepNum" $ enumerateFromStepNum size
src/Streamly/Internal/Data/Unfold.hs+25−144
@@ -142,19 +142,34 @@ module Streamly.Internal.Data.Unfold
142142
143143 -- ** Enumerations
144144 , Enumerable (..)
145− -- *** Enumerate Num
146− , enumerateFromStepNum
147− , numFrom
148145
149− -- *** Enumerate Integral
150− , enumerateFromStepIntegral
151− , enumerateFromToIntegral
146+ -- ** Enumerate Num
147+ , enumerateFromNum
148+ , enumerateFromThenNum
149+
150+ -- ** Enumerating 'Bounded 'Integral' Types
151+ , enumerateFromIntegralBounded
152+ , enumerateFromThenIntegralBounded
153+ , enumerateFromToIntegralBounded
154+ , enumerateFromThenToIntegralBounded
155+
156+ -- ** Enumerating 'Unounded Integral' Types
152157 , enumerateFromIntegral
158+ , enumerateFromThenIntegral
159+ , enumerateFromToIntegral
160+ , enumerateFromThenToIntegral
161+
162+ -- ** Enumerating 'Small Integral' Types
163+ , enumerateFromSmall
164+ , enumerateFromThenSmall
165+ , enumerateFromToSmall
166+ , enumerateFromThenToSmall
153167
154− -- *** Enumerate Fractional
155− -- | Use 'Num' enumerations for fractional or floating point number
156− -- enumerations.
168+ -- ** Enumerating 'Fractional' Types
169+ , enumerateFromFractional
170+ , enumerateFromThenFractional
157171 , enumerateFromToFractional
172+ , enumerateFromThenToFractional
158173
159174 -- ** From Containers
160175 , fromList
@@ -230,20 +245,16 @@ module Streamly.Internal.Data.Unfold
230245 )
231246where
232247
233−import Control.Exception (Exception, fromException, mask_)
234−import Control.Monad ((>=>), when)
248+import Control.Exception (Exception, mask_)
235249import Control.Monad.Catch (MonadCatch)
236250import Control.Monad.IO.Class (MonadIO(..))
237251import Control.Monad.Trans.Control (MonadBaseControl, liftBaseOp_)
238−import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef)
239−import Data.Maybe (isNothing)
240252import GHC.Types (SPEC(..))
241253import Streamly.Internal.Control.Concurrent (MonadAsync)
242254import Streamly.Internal.Data.Fold.Type (Fold(..))
243255import Streamly.Internal.Data.IOFinalizer
244256 (newIOFinalizer, runIOFinalizer, clearingIOFinalizer)
245257import Streamly.Internal.Data.Stream.StreamD.Type (Stream(..), Step(..))
246−import Streamly.Internal.Data.SVar.Type (defState)
247258
248259import qualified Control.Monad.Catch as MC
249260import qualified Data.Tuple as Tuple
@@ -252,7 +263,6 @@ import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
252263import qualified Streamly.Internal.Data.Stream.StreamK as K (uncons)
253264import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
254265
255−import Streamly.Internal.Data.Unfold.Type
256266import Streamly.Internal.Data.SVar
257267import Streamly.Internal.Data.Unfold.Enumeration
258268import Streamly.Internal.Data.Unfold.Type
@@ -733,135 +743,6 @@ dropWhileM f (Unfold step inject) = Unfold step' inject'
733743dropWhile :: Monad m => (b -> Bool) -> Unfold m a b -> Unfold m a b
734744dropWhile f = dropWhileM (return . f)
735745
736−-------------------------------------------------------------------------------
737−-- Generation from SVar
738−-------------------------------------------------------------------------------
739−
740−data FromSVarState t m a =
741− FromSVarInit (SVar t m a)
742− | FromSVarRead (SVar t m a)
743− | FromSVarLoop (SVar t m a) [ChildEvent a]
744− | FromSVarDone (SVar t m a)
745−
746−-- | /Internal/
747−--
748−{-# INLINE_NORMAL fromSVar #-}
749−fromSVar :: MonadAsync m => Unfold m (SVar t m a) a
750−fromSVar = Unfold step (return . FromSVarInit)
751− where
752−
753− {-# INLINE_LATE step #-}
754− step (FromSVarInit svar) = do
755− ref <- liftIO $ newIORef ()
756− _ <- liftIO $ mkWeakIORef ref hook
757− -- when this copy of svar gets garbage collected "ref" will get
758− -- garbage collected and our GC hook will be called.
759− let sv = svar{svarRef = Just ref}
760− return $ Skip (FromSVarRead sv)
761−
762− where
763−
764− {-# NOINLINE hook #-}
765− hook = do
766− when (svarInspectMode svar) $ do
767− r <- liftIO $ readIORef (svarStopTime (svarStats svar))
768− when (isNothing r) $
769− printSVar svar "SVar Garbage Collected"
770− cleanupSVar svar
771− -- If there are any SVars referenced by this SVar a GC will prompt
772− -- them to be cleaned up quickly.
773− when (svarInspectMode svar) performMajorGC
774−
775− step (FromSVarRead sv) = do
776− list <- readOutputQ sv
777− -- Reversing the output is important to guarantee that we process the
778− -- outputs in the same order as they were generated by the constituent
779− -- streams.
780− return $ Skip $ FromSVarLoop sv (Prelude.reverse list)
781−
782− step (FromSVarLoop sv []) = do
783− done <- postProcess sv
784− return $ Skip $ if done
785− then FromSVarDone sv
786− else FromSVarRead sv
787−
788− step (FromSVarLoop sv (ev : es)) = do
789− case ev of
790− ChildYield a -> return $ Yield a (FromSVarLoop sv es)
791− ChildStop tid e -> do
792− accountThread sv tid
793− case e of
794− Nothing -> do
795− stop <- shouldStop tid
796− if stop
797− then do
798− liftIO (cleanupSVar sv)
799− return $ Skip (FromSVarDone sv)
800− else return $ Skip (FromSVarLoop sv es)
801− Just ex ->
802− case fromException ex of
803− Just ThreadAbort ->
804− return $ Skip (FromSVarLoop sv es)
805− Nothing -> liftIO (cleanupSVar sv) >> MC.throwM ex
806− where
807−
808− shouldStop tid =
809− case svarStopStyle sv of
810− StopNone -> return False
811− StopAny -> return True
812− StopBy -> do
813− sid <- liftIO $ readIORef (svarStopBy sv)
814− return $ tid == sid
815−
816− step (FromSVarDone sv) = do
817− when (svarInspectMode sv) $ do
818− t <- liftIO $ getTime Monotonic
819− liftIO $ writeIORef (svarStopTime (svarStats sv)) (Just t)
820− liftIO $ printSVar sv "SVar Done"
821− return Stop
822−
823−-------------------------------------------------------------------------------
824−-- Process events received by a fold consumer from a stream producer
825−-------------------------------------------------------------------------------
826−
827−-- XXX Have an error for "FromSVarInit" instead of undefined. The error can
828−-- redirect the user to report the failure to the developers.
829−-- | /Internal/
830−--
831−{-# INLINE_NORMAL fromProducer #-}
832−fromProducer :: MonadAsync m => Unfold m (SVar t m a) a
833−fromProducer = Unfold step (return . FromSVarRead)
834− where
835−
836− {-# INLINE_LATE step #-}
837− step (FromSVarRead sv) = do
838− list <- readOutputQ sv
839− -- Reversing the output is important to guarantee that we process the
840− -- outputs in the same order as they were generated by the constituent
841− -- streams.
842− return $ Skip $ FromSVarLoop sv (Prelude.reverse list)
843−
844− step (FromSVarLoop sv []) = return $ Skip $ FromSVarRead sv
845− step (FromSVarLoop sv (ev : es)) = do
846− case ev of
847− ChildYield a -> return $ Yield a (FromSVarLoop sv es)
848− ChildStop tid e -> do
849− accountThread sv tid
850− case e of
851− Nothing -> do
852− sendStopToProducer sv
853− return $ Skip (FromSVarDone sv)
854− Just _ -> error "Bug: fromProducer: received exception"
855−
856− step (FromSVarDone sv) = do
857− when (svarInspectMode sv) $ do
858− t <- liftIO $ getTime Monotonic
859− liftIO $ writeIORef (svarStopTime (svarStats sv)) (Just t)
860− liftIO $ printSVar sv "SVar Done"
861− return Stop
862−
863− step (FromSVarInit _) = undefined
864−
865746------------------------------------------------------------------------------
866747-- Exceptions
867748------------------------------------------------------------------------------
src/Streamly/Internal/Data/Unfold/Enumeration.hs+371−82
@@ -23,32 +23,39 @@ module Streamly.Internal.Data.Unfold.Enumeration
2323 (
2424 Enumerable (..)
2525
26− -- ** Enumerate Num
27− , enumerateFromStepNum
28− , numFrom
29− , numFromThen
26+ -- ** Enumerate 'Num' Types
27+ , enumerateFromNum
28+ , enumerateFromThenNum
3029
31− -- ** Enumerating 'Bounded' 'Integral' Types
30+ -- ** Enumerating 'Bounded Integral' Types
31+ , enumerateFromIntegralBounded
32+ , enumerateFromThenIntegralBounded
33+ , enumerateFromToIntegralBounded
34+ , enumerateFromThenToIntegralBounded
35+
36+ -- ** Enumerating 'Unbounded Integral' Types
3237 , enumerateFromIntegral
3338 , enumerateFromThenIntegral
34−
35− -- ** Enumerating 'Integral' Types
3639 , enumerateFromToIntegral
3740 , enumerateFromThenToIntegral
3841
39− -- ** Enumerating unbounded 'Integral' Types
40− , enumerateFromStepIntegral
42+ -- ** Enumerating 'Small Integral' Types
43+ , enumerateFromSmall
44+ , enumerateFromThenSmall
45+ , enumerateFromToSmall
46+ , enumerateFromThenToSmall
4147
4248 -- ** Enumerating 'Fractional' Types
4349 , enumerateFromFractional
44− , enumerateFromToFractional
4550 , enumerateFromThenFractional
51+ , enumerateFromToFractional
4652 , enumerateFromThenToFractional
4753 )
4854where
4955
5056#include "inline.hs"
5157import Data.Fixed
58+import Data.Bifunctor (bimap)
5259import Data.Int
5360import Data.Ratio
5461import Data.Word
@@ -64,36 +71,102 @@ import Prelude
6471-- Enumeration of Num
6572------------------------------------------------------------------------------
6673
67−-- | Generate an infinite stream starting from a starting value with increments
68−-- of the given stride. The implementation is numerically stable for floating
74+-- | Generate an infinite stream starting from a starting value with default
75+-- stride of value 1. The implementation is numerically stable for floating
6976-- point values.
7077--
7178-- Note 'enumerateFromStepIntegral' is faster for integrals.
7279--
7380-- /Pre-release/
7481--
75−{-# INLINE enumerateFromStepNum #-}
76−enumerateFromStepNum :: (Monad m, Num a) => a -> Unfold m a a
77−enumerateFromStepNum stride = Unfold step inject
82+{-# INLINE enumerateFromNum #-}
83+enumerateFromNum :: (Monad m, Num a) => Unfold m a a
84+enumerateFromNum = Unfold step inject
7885
7986 where
8087
81− inject !from = return (from, 0)
88+ inject !from = return (from, 1, 0)
8289
8390 {-# INLINE_LATE step #-}
84− step (from, !i) = return $ (Yield $! (from + i * stride)) $! (from, i + 1)
91+ step (from, stride, i) =
92+ return $
93+ (Yield $! (from + i * stride)) $! (from, stride, i + 1)
94+
95+-- | Generate an infinite stream starting from a from and next values with
96+-- stride of (next-from). The implementation is numerically stable for
97+-- floating point values.
98+--
99+-- Note 'enumerateFromStepIntegral' is faster for integrals.
100+--
101+-- /Pre-release/
102+--
103+{-# INLINE enumerateFromThenNum #-}
104+enumerateFromThenNum :: (Monad m, Num a) => Unfold m (a, a) a
105+enumerateFromThenNum = Unfold step inject
106+
107+ where
108+
109+ inject (!from, !next) = return (from, next - from, 0)
110+
111+ {-# INLINE_LATE step #-}
112+ step (from, stride, i) =
113+ return $
114+ (Yield $! (from + i * stride)) $! (from, stride, i + 1)
115+
116+-- | Generate a finite stream starting from a from and next values with
117+-- stride of (next-from) till to value. The implementation is numerically
118+-- stable for floating point values.
119+--
120+-- Note 'enumerateFromStepIntegral' is faster for integrals.
121+--
122+-- /Pre-release/
123+--
124+{-# INLINE enumerateFromThenToNumBounded #-}
125+enumerateFromThenToNumBounded :: (Monad m, Ord a, Fractional a) =>
126+ Unfold m (a, a, a) a
127+enumerateFromThenToNumBounded = Unfold step inject
128+
129+ where
130+
131+ inject (!from, !next, !to) = return (from, next - from, to, 0)
85132
86−-- | @numFrom = enumerateFromStepNum 1@
133+ {-# INLINE_LATE step #-}
134+ step (from, stride, to, !i) = return $
135+ if stride == 0
136+ then if from <= to then Yield from $! (from, stride, to, i + 1) else Stop
137+ else
138+ if stride > 0
139+ then
140+ if (from + i * stride) <= to + stride / 2
141+ then (Yield $! (from + i * stride)) $! (from, stride, to, i + 1)
142+ else Stop
143+ else
144+ if (from + i * stride) >= to + stride / 2
145+ then (Yield $! (from + i * stride)) $! (from, stride, to, i + 1)
146+ else Stop
147+
148+-- | Generate a finite stream starting from a from till to value.
149+-- stride of value 1 will be used. The implementation is numerically
150+-- stable for floating point values.
151+--
152+-- Note 'enumerateFromStepIntegralBounded' is faster for integrals.
87153--
88154-- /Pre-release/
89155--
90−{-# INLINE_NORMAL numFrom #-}
91−numFrom :: (Monad m, Num a) => Unfold m a a
92−numFrom = enumerateFromStepNum 1
156+{-# INLINE enumerateFromToNumBounded #-}
157+enumerateFromToNumBounded :: (Monad m, Ord a, Fractional a) =>
158+ Unfold m (a, a) a
159+enumerateFromToNumBounded = Unfold step inject
160+
161+ where
93162
94−{-# INLINE_NORMAL numFromThen #-}
95−numFromThen :: (Monad m, Num a) => a -> Unfold m a a
96−numFromThen = enumerateFromStepNum
163+ inject (!from, !to) = return (from, 1, to, 0)
164+
165+ {-# INLINE_LATE step #-}
166+ step (from, !stride, to, !i) = return $
167+ if (from + i * stride) <= to + stride / 2
168+ then (Yield $! (from + i * stride)) $! (from, stride, to, i + 1)
169+ else Stop
97170
98171------------------------------------------------------------------------------
99172-- Enumeration of Integrals
@@ -105,55 +178,159 @@ numFromThen = enumerateFromStepNum
105178enumerateFromStepIntegral :: (Integral a, Monad m) => Unfold m (a, a) a
106179enumerateFromStepIntegral = Unfold step inject
107180 where
108− inject (from, stride) = from `seq` stride `seq` return (from, stride)
181+ inject (from, next) = from `seq` next `seq` return (from, next - from)
109182 {-# INLINE_LATE step #-}
110183 step (x, stride) = return $ Yield x $! (x + stride, stride)
111184
112−-- We are assuming that "to" is constrained by the type to be within
113−-- max/min bounds.
114−{-# INLINE enumerateFromToIntegral #-}
115−enumerateFromToIntegral :: (Monad m, Integral a) => a -> Unfold m a a
116−enumerateFromToIntegral to =
117− takeWhile (<= to) $ supplySecond 1 enumerateFromStepIntegral
118−
119−{-# INLINE enumerateFromThenToIntegral #-}
120−enumerateFromThenToIntegral :: (Monad m, Integral a) => a -> a -> Unfold m a a
121−enumerateFromThenToIntegral stride to =
122− takeWhile (<= to) $ supplySecond stride enumerateFromStepIntegral
123−
185+-- | Can be used to enumerate bounded integrals from starting from with
186+-- stride of (next-from) . This check for overflow or underflow for
187+-- bounded integrals.
188+-- /Pre-release/
189+--
190+{-# INLINE_NORMAL enumerateFromStepIntegralBounded #-}
191+enumerateFromStepIntegralBounded ::
192+ forall a m. (Integral a, Bounded a, Monad m) =>
193+ Unfold m (a, a) a
194+enumerateFromStepIntegralBounded = Unfold step inject
195+ where
196+ inject (from, next) =
197+ from `seq` next `seq` return (from, next - from)
198+ {-# INLINE_LATE step #-}
199+ step (x, stride) = return $
200+ if stride == 0
201+ then
202+ Yield x $! (x, stride)
203+
204+ else
205+ if stride > 0
206+ then
207+ if x <= (maxBound :: a)
208+ then Yield x $! (x + stride, stride)
209+ else Stop
210+ else
211+ if x >= (minBound :: a)
212+ then Yield x $! (x + stride, stride)
213+ else Stop
214+
215+-- | Can be used to enumerate bounded integrals from starting from with
216+-- stride of (next-from) till to value. This check for overflow or underflow
217+-- for bounded integrals.
218+-- /Pre-release/
219+--
220+{-# INLINE_NORMAL enumerateFromToStepIntegralBounded #-}
221+enumerateFromToStepIntegralBounded ::
222+ forall a m. (Integral a, Bounded a, Monad m) =>
223+ Unfold m (a, a, a) a
224+enumerateFromToStepIntegralBounded = Unfold step inject
225+ where
226+ inject (from, next, to) =
227+ from `seq` next `seq` to `seq` return (from, next - from, to)
228+ {-# INLINE_LATE step #-}
229+ step (x, stride, to) = return $
230+ if stride == 0
231+ then
232+ if x <= to then Yield x $! (x, stride, to) else Stop
233+
234+ else
235+ if stride > 0
236+ then
237+ if x <= to && x <= (maxBound :: a)
238+ then Yield x $! (x + stride, stride, to)
239+ else Stop
240+ else
241+ if x >= to && x >= (minBound :: a)
242+ then Yield x $! (x + stride, stride, to)
243+ else Stop
244+
245+-- | Can be used to enumerate unbounded integrals. Startting with value from
246+-- with stride of next-from till value of to.
247+-- /Pre-release/
248+--
249+{-# INLINE_NORMAL enumerateFromToStepIntegral #-}
250+enumerateFromToStepIntegral :: (Integral a, Monad m) =>
251+ Unfold m (a, a, a) a
252+enumerateFromToStepIntegral = Unfold step inject
253+ where
254+ inject (from, next, to) =
255+ from `seq` next `seq` to `seq` return (from, next - from, to)
256+ {-# INLINE_LATE step #-}
257+ step (x, stride, to) = return $
258+ if stride == 0
259+ then
260+ if x <= to then Yield x $! (x, stride, to) else Stop
261+
262+ else
263+ if stride > 0
264+ then
265+ if x <= to
266+ then Yield x $! (x + stride, stride, to)
267+ else Stop
268+ else
269+ if x >= to
270+ then Yield x $! (x + stride, stride, to)
271+ else Stop
272+
273+-- Enumerate Unbounded Integrals ----------------------------------------------
124274{-# INLINE enumerateFromIntegral #-}
125−enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => Unfold m a a
126−enumerateFromIntegral = enumerateFromToIntegral maxBound
275+enumerateFromIntegral :: (Monad m, Integral a) => Unfold m a a
276+enumerateFromIntegral = supplyNextFromStride (+ 1) enumerateFromStepIntegral
127277
128278{-# INLINE enumerateFromThenIntegral #-}
129−enumerateFromThenIntegral :: (Monad m, Integral a, Bounded a) => a -> Unfold m a a
130−enumerateFromThenIntegral stride = enumerateFromThenToIntegral stride maxBound
279+enumerateFromThenIntegral :: (Monad m, Integral a ) => Unfold m (a, a) a
280+enumerateFromThenIntegral = enumerateFromStepIntegral
281+
282+{-# INLINE enumerateFromToIntegral #-}
283+enumerateFromToIntegral :: (Monad m, Integral a) => Unfold m (a, a) a
284+enumerateFromToIntegral = supplyMiddle (+ 1) enumerateFromToStepIntegral
285+
286+{-# INLINE enumerateFromThenToIntegral #-}
287+enumerateFromThenToIntegral :: (Monad m, Integral a) => Unfold m (a, a, a) a
288+enumerateFromThenToIntegral = enumerateFromToStepIntegral
289+
290+-- Enumerate Bounded Integrals ------------------------------------------------
291+{-# INLINE enumerateFromIntegralBounded #-}
292+enumerateFromIntegralBounded :: (Monad m, Bounded a, Integral a) =>
293+ Unfold m a a
294+enumerateFromIntegralBounded =
295+ supplySecondThird (+ 1) maxBound enumerateFromToStepIntegralBounded
296+
297+{-# INLINE enumerateFromThenIntegralBounded #-}
298+enumerateFromThenIntegralBounded :: (Monad m, Bounded a, Integral a ) =>
299+ Unfold m (a, a) a
300+enumerateFromThenIntegralBounded = enumerateFromStepIntegralBounded
301+
302+{-# INLINE enumerateFromToIntegralBounded #-}
303+enumerateFromToIntegralBounded :: (Monad m, Integral a, Bounded a) =>
304+ Unfold m (a, a) a
305+enumerateFromToIntegralBounded =
306+ supplyMiddle (+ 1) enumerateFromToStepIntegralBounded
307+
308+{-# INLINE enumerateFromThenToIntegralBounded #-}
309+enumerateFromThenToIntegralBounded :: (Monad m, Integral a, Bounded a) =>
310+ Unfold m (a, a, a) a
311+enumerateFromThenToIntegralBounded = enumerateFromToStepIntegralBounded
131312
132313------------------------------------------------------------------------------
133314-- Enumeration of Fractionals
134315------------------------------------------------------------------------------
135316
136−-- | /Internal/
137−--
138−-- > enumerateFromToFractional to = takeWhile (<= to + 1 / 2) $ enumerateFromStepNum 1
139−--
140−{-# INLINE_NORMAL enumerateFromToFractional #-}
141−enumerateFromToFractional :: (Monad m, Fractional a, Ord a) => a -> Unfold m a a
142−enumerateFromToFractional to =
143− takeWhile (<= to + 1 / 2) $ enumerateFromStepNum 1
144−
145317{-# INLINE_NORMAL enumerateFromFractional #-}
146318enumerateFromFractional :: (Monad m, Fractional a) => Unfold m a a
147−enumerateFromFractional = enumerateFromStepNum 1
148−
149−{-# INLINE_NORMAL enumerateFromThenToFractional #-}
150−enumerateFromThenToFractional :: (Monad m, Fractional a, Ord a) => a -> a -> Unfold m a a
151−enumerateFromThenToFractional stride to =
152− takeWhile (<= to + 1 / 2) $ enumerateFromStepNum stride
319+enumerateFromFractional = enumerateFromNum
153320
154321{-# INLINE_NORMAL enumerateFromThenFractional #-}
155−enumerateFromThenFractional :: (Monad m, Fractional a) => a -> Unfold m a a
156−enumerateFromThenFractional = enumerateFromStepNum
322+enumerateFromThenFractional :: (Monad m, Fractional a) => Unfold m (a, a) a
323+enumerateFromThenFractional = enumerateFromThenNum
324+
325+{-# INLINE_NORMAL enumerateFromToFractional #-}
326+enumerateFromToFractional :: (Monad m, Fractional a, Ord a) =>
327+ Unfold m (a, a) a
328+enumerateFromToFractional = enumerateFromToNumBounded
329+
330+{-# INLINE_NORMAL enumerateFromThenToFractional #-}
331+enumerateFromThenToFractional :: (Monad m, Fractional a, Ord a) =>
332+ Unfold m (a, a, a) a
333+enumerateFromThenToFractional = enumerateFromThenToNumBounded
157334
158335-------------------------------------------------------------------------------
159336-- Enumerable type class
@@ -212,7 +389,7 @@ class Enum a => Enumerable a where
212389-- @
213390--
214391-- /Pre-release/
215− enumerateFromTo :: Monad m => a -> Unfold m a a
392+ enumerateFromTo :: Monad m => Unfold m (a, a) a
216393
217394-- @enumerateFromThen from then@ generates a stream whose first element
218395-- is @from@ and the successive elements are
@@ -231,7 +408,7 @@ class Enum a => Enumerable a where
231408-- @
232409--
233410-- /Pre-release/
234− enumerateFromThen :: Monad m => a -> Unfold m a a
411+ enumerateFromThen :: Monad m => Unfold m (a, a) a
235412
236413-- @enumerateFromThenTo from then to@ generates a finite stream whose
237414-- first element is @from@ and the successive elements are in
@@ -249,7 +426,112 @@ class Enum a => Enumerable a where
249426-- @
250427--
251428-- /Pre-release/
252− enumerateFromThenTo :: Monad m => a-> a -> Unfold m a a
429+ enumerateFromThenTo :: Monad m => Unfold m (a, a, a) a
430+
431+-------------------------------------------------------------------------------
432+-- Enumeration of Enum types not larger than Int
433+-------------------------------------------------------------------------------
434+
435+-- Enumerate from given starting Enum value 'from' with stride of 1 till
436+-- maxBound
437+-- /Pre-release/
438+--
439+{-# INLINE enumerateFromSmall #-}
440+enumerateFromSmall :: forall a m. (Monad m, Bounded a, Enum a) => Unfold m a a
441+enumerateFromSmall = map toEnum $
442+ Unfold step inject
443+ where
444+ inject from =
445+ fromEnum from
446+ `seq` return (fromEnum from, 1, fromEnum (maxBound :: a))
447+ {-# INLINE_LATE step #-}
448+ step (x, stride, to) = return $
449+ if x <= to then Yield x $! (x + stride, stride, to) else Stop
450+
451+-- Enumerate from given starting Enum value 'from' and next Enum value 'next'
452+-- with stride of (fromEnum next - fromEnum from) till maxBound.
453+-- /Pre-release/
454+--
455+{-# INLINE enumerateFromThenSmall #-}
456+enumerateFromThenSmall :: forall a m. (Monad m, Bounded a, Enum a) =>
457+ Unfold m (a, a) a
458+enumerateFromThenSmall = map toEnum $
459+ Unfold step inject
460+ where
461+ inject (from, next) =
462+ fromEnum from
463+ `seq` fromEnum next
464+ `seq` return
465+ ( fromEnum from
466+ , fromEnum next - fromEnum from
467+ , fromEnum (maxBound :: a)
468+ )
469+ {-# INLINE_LATE step #-}
470+ step (x, stride, to) = return $
471+ if stride == 0
472+ then
473+ if x <= to then Yield x $! (x, stride, to) else Stop
474+
475+ else
476+ if stride > 0
477+ then
478+ if x <= to
479+ then Yield x $! (x + stride, stride, to)
480+ else Stop
481+ else
482+ if x >= 0
483+ then Yield x $! (x + stride, stride, to)
484+ else Stop
485+
486+-- Enumerate from given starting Enum value 'from' and to Enum value 'to'
487+-- with stride of 1 till to value.
488+-- /Pre-release/
489+--
490+{-# INLINE enumerateFromToSmall #-}
491+enumerateFromToSmall :: (Monad m, Enum a) => Unfold m (a, a) a
492+enumerateFromToSmall = map toEnum $
493+ Unfold step inject
494+ where
495+ inject (from, to) =
496+ fromEnum from
497+ `seq` fromEnum to
498+ `seq` return (fromEnum from, 1, fromEnum to)
499+ {-# INLINE_LATE step #-}
500+ step (x, stride, to) = return $
501+ if x <= to then Yield x $! (x + stride, stride, to) else Stop
502+
503+-- Enumerate from given starting Enum value 'from' and then Enum value 'next'
504+-- and to Enum value 'to' with stride of (fromEnum next - fromEnum from)
505+-- till to value.
506+-- /Pre-release/
507+--
508+{-# INLINE enumerateFromThenToSmall #-}
509+enumerateFromThenToSmall :: (Monad m, Enum a) => Unfold m (a, a, a) a
510+enumerateFromThenToSmall = map toEnum $
511+ Unfold step inject
512+ where
513+ inject (from, next, to) =
514+ fromEnum from
515+ `seq` fromEnum next
516+ `seq` fromEnum to
517+ `seq` return
518+ (fromEnum from, fromEnum next - fromEnum from, fromEnum to)
519+ {-# INLINE_LATE step #-}
520+ step (x, stride, to) = return $
521+ if stride == 0
522+ then
523+ if x <= to then Yield x $! (x, stride, to) else Stop
524+
525+ else
526+ if stride > 0
527+ then
528+ if x <= to
529+ then Yield x $! (x + stride, stride, to)
530+ else Stop
531+ else
532+ if x >= 0 && x >= to
533+ then Yield x $! (x + stride, stride, to)
534+ else Stop
253535
254536-------------------------------------------------------------------------------
255537-- Enumerable Instances
@@ -259,13 +541,13 @@ class Enum a => Enumerable a where
259541#define ENUMERABLE_BOUNDED_SMALL(SMALL_TYPE) \
260542instance Enumerable SMALL_TYPE where { \
261543 {-# INLINE enumerateFrom #-}; \
262− enumerateFrom = undefined; \
544+ enumerateFrom = enumerateFromSmall; \
263545 {-# INLINE enumerateFromThen #-}; \
264− enumerateFromThen = undefined; \
546+ enumerateFromThen = enumerateFromThenSmall; \
265547 {-# INLINE enumerateFromTo #-}; \
266− enumerateFromTo = undefined; \
548+ enumerateFromTo = enumerateFromToSmall; \
267549 {-# INLINE enumerateFromThenTo #-}; \
268− enumerateFromThenTo = undefined }
550+ enumerateFromThenTo = enumerateFromThenToSmall }
269551
270552ENUMERABLE_BOUNDED_SMALL(())
271553ENUMERABLE_BOUNDED_SMALL(Bool)
@@ -273,16 +555,16 @@ ENUMERABLE_BOUNDED_SMALL(Ordering)
273555ENUMERABLE_BOUNDED_SMALL(Char)
274556
275557-- For bounded Integral Enum types, may be larger than Int.
276−#define ENUMERABLE_BOUNDED_INTEGRAL(INTEGRAL_TYPE) \
277−instance Enumerable INTEGRAL_TYPE where { \
278− {-# INLINE enumerateFrom #-}; \
279− enumerateFrom = enumerateFromIntegral; \
280− {-# INLINE enumerateFromThen #-}; \
281− enumerateFromThen = enumerateFromThenIntegral; \
282− {-# INLINE enumerateFromTo #-}; \
283− enumerateFromTo = enumerateFromToIntegral; \
284− {-# INLINE enumerateFromThenTo #-}; \
285− enumerateFromThenTo = enumerateFromThenToIntegral }
558+#define ENUMERABLE_BOUNDED_INTEGRAL(INTEGRAL_TYPE) \
559+instance Enumerable INTEGRAL_TYPE where { \
560+ {-# INLINE enumerateFrom #-}; \
561+ enumerateFrom = enumerateFromIntegralBounded; \
562+ {-# INLINE enumerateFromThen #-}; \
563+ enumerateFromThen = enumerateFromThenIntegralBounded; \
564+ {-# INLINE enumerateFromTo #-}; \
565+ enumerateFromTo = enumerateFromToIntegralBounded; \
566+ {-# INLINE enumerateFromThenTo #-}; \
567+ enumerateFromThenTo = enumerateFromThenToIntegralBounded }
286568
287569ENUMERABLE_BOUNDED_INTEGRAL(Int)
288570ENUMERABLE_BOUNDED_INTEGRAL(Int8)
@@ -299,10 +581,9 @@ ENUMERABLE_BOUNDED_INTEGRAL(Word64)
299581#define ENUMERABLE_UNBOUNDED_INTEGRAL(INTEGRAL_TYPE) \
300582instance Enumerable INTEGRAL_TYPE where { \
301583 {-# INLINE enumerateFrom #-}; \
302− enumerateFrom = supplySecond 1 enumerateFromStepIntegral; \
584+ enumerateFrom = enumerateFromIntegral; \
303585 {-# INLINE enumerateFromThen #-}; \
304− enumerateFromThen next = \
305− lmap (\from -> (from, next - from)) enumerateFromStepIntegral; \
586+ enumerateFromThen = enumerateFromThenIntegral; \
306587 {-# INLINE enumerateFromTo #-}; \
307588 enumerateFromTo = enumerateFromToIntegral; \
308589 {-# INLINE enumerateFromThenTo #-}; \
@@ -329,10 +610,18 @@ ENUMERABLE_FRACTIONAL((Ratio a),Integral a)
329610
330611instance Enumerable a => Enumerable (Identity a) where
331612 {-# INLINE enumerateFrom #-}
332− enumerateFrom = map Identity $ lmap runIdentity enumerateFrom
613+ enumerateFrom =
614+ map Identity $ lmap runIdentity enumerateFrom
333615 {-# INLINE enumerateFromThen #-}
334− enumerateFromThen = undefined
616+ enumerateFromThen =
617+ map Identity $ lmap (bimap runIdentity runIdentity) enumerateFromThen
335618 {-# INLINE enumerateFromTo #-}
336− enumerateFromTo = undefined
619+ enumerateFromTo =
620+ map Identity $ lmap (bimap runIdentity runIdentity) enumerateFromThen
337621 {-# INLINE enumerateFromThenTo #-}
338− enumerateFromThenTo = undefined
622+ enumerateFromThenTo =
623+ map Identity $
624+ lmap
625+ (\(from, next, to) ->
626+ (runIdentity from, runIdentity next, runIdentity to))
627+ enumerateFromThenTo
src/Streamly/Internal/Data/Unfold/Type.hs+35−1
@@ -34,7 +34,10 @@ module Streamly.Internal.Data.Unfold.Type
3434 , map
3535 , supply
3636 , supplyFirst
37− , supplySecond
37+ , supplySecond
38+ , supplyMiddle
39+ , supplySecondThird
40+ , supplyNextFromStride
3841 , takeWhileM
3942 , takeWhile
4043
@@ -218,6 +221,37 @@ supplyFirst a = lmap (a, )
218221supplySecond :: b -> Unfold m (a, b) c -> Unfold m a c
219222supplySecond b = lmap (, b)
220223
224+-- | Supply the second and third components of the tuple to an unfold that
225+-- accepts a tuple as a seed resulting in a fold that accepts the first
226+-- component of the tuple as a seed.
227+--
228+-- /Pre-release/
229+--
230+{-# INLINE_NORMAL supplySecondThird #-}
231+supplySecondThird :: (a -> b) -> c -> Unfold m (a, b, c) x -> Unfold m a x
232+supplySecondThird f c = lmap (\a -> (a, f a, c))
233+
234+-- | Supply the second component of the tuple to an unfold that accepts a tuple
235+-- as a seed and resulting in a fold that accepts the first and second
236+-- components of the tuple as a seed.
237+--
238+-- /Pre-release/
239+--
240+{-# INLINE_NORMAL supplyMiddle #-}
241+supplyMiddle :: (a -> b) -> Unfold m (a, b, c) x -> Unfold m (a, c) x
242+supplyMiddle f = lmap (\(a, c) -> (a, f a, c))
243+
244+-- | Supply the next component of the tuple to an unfold that accepts a tuple
245+-- as a seed resulting in a fold that accepts the first component of the tuple
246+-- as a seed.
247+-- next component of tuple is (first + stride)
248+--
249+-- /Pre-release/
250+--
251+{-# INLINE_NORMAL supplyNextFromStride #-}
252+supplyNextFromStride :: (a -> b) -> Unfold m (a, b) c -> Unfold m a c
253+supplyNextFromStride f = lmap (\a -> (a, f a))
254+
221255------------------------------------------------------------------------------
222256-- Filter input
223257------------------------------------------------------------------------------
streamly.cabal+1−2
@@ -422,8 +422,7 @@ library
422422 -- streamly-core
423423 , Streamly.Internal.Data.Unfold
424424 , Streamly.Internal.Data.Unfold.SVar
425− , Streamly.Internal.Data.Unfold.Enumeration
426− , Streamly.Internal.Data.Unfold
425+ , Streamly.Internal.Data.Unfold.Enumeration
427426 , Streamly.Internal.Data.Fold.Tee
428427 , Streamly.Internal.Data.Fold
429428 , Streamly.Internal.Data.Fold.SVar
test/Streamly/Test/Data/Unfold.hs+289−39
@@ -195,37 +195,255 @@ fromIndicesM =
195195 unf = UF.take 100 $ UF.fromIndicesM indFM
196196 in testUnfoldMD unf 1 0 (length list) list
197197
198−enumerateFromStepNum :: Property
199−enumerateFromStepNum =
198+-------------------------------------------------------------------------------
199+-- Test for Num type -----------------------------------------------------
200+-------------------------------------------------------------------------------
201+enumerateFromNum :: Property
202+enumerateFromNum =
200203 property
201− $ \f s ->
202− let unf = UF.take 10 $ UF.enumerateFromStepNum s
203− lst = Prelude.take 10 $ List.unfoldr (\x -> Just (x, x + s)) f
204− in testUnfoldD unf f lst
204+ $ \f ->
205+ let unf = UF.take 50 UF.enumerateFromNum
206+ in testUnfold unf (f :: Int) $
207+ Prelude.take 50 $ Prelude.enumFrom f
205208
206−#if MIN_VERSION_base(4,12,0)
207−enumerateFromToFractional :: Property
208−enumerateFromToFractional =
209+enumerateFromThenNum :: Property
210+enumerateFromThenNum =
209211 property
210− $ \f t ->
211− let unf = UF.enumerateFromToFractional (t :: Double)
212− in testUnfold unf (f :: Double) [f..(t :: Double)]
213−#endif
212+ $ \f th ->
213+ let unf = UF.take 50 UF.enumerateFromThenNum
214+ in testUnfold unf (f :: Int, th) $
215+ Prelude.take 50 $ Prelude.enumFromThen f th
216+
217+-------------------------------------------------------------------------------
218+-- Test for Integral type -----------------------------------------------------
219+-------------------------------------------------------------------------------
220+enumerateFromIntegral :: Property
221+enumerateFromIntegral =
222+ property
223+ $ \f ->
224+ let unf = UF.take 50 UF.enumerateFromIntegral
225+ in testUnfold unf (f :: Integer) $
226+ Prelude.take 50 $ Prelude.enumFrom f
227+
228+enumerateFromThenIntegral :: Property
229+enumerateFromThenIntegral =
230+ property
231+ $ \f th ->
232+ let unf = UF.take 50 UF.enumerateFromThenIntegral
233+ in testUnfold unf (f :: Integer, th) $
234+ Prelude.take 50 $ Prelude.enumFromThen f th
214235
215−enumerateFromStepIntegral :: Property
216−enumerateFromStepIntegral =
236+enumerateFromThenToIntegral :: Property
237+enumerateFromThenToIntegral =
217238 property
218− $ \f s ->
219− let unf = UF.take 10 UF.enumerateFromStepIntegral
220− lst = Prelude.take 10 $ List.unfoldr (\x -> Just (x, x + s)) f
221− in testUnfoldD unf (f, s) lst
239+ $ \f th to ->
240+ let unf = UF.take 50 UF.enumerateFromThenToIntegral
241+ in testUnfold unf (f :: Integer, th, to) $
242+ Prelude.take 50 $ Prelude.enumFromThenTo f th to
222243
223244enumerateFromToIntegral :: Property
224245enumerateFromToIntegral =
246+ property
247+ $ \f to ->
248+ let unf = UF.take 50 UF.enumerateFromToIntegral
249+ in testUnfold unf (f :: Integer, to) $
250+ Prelude.take 50 $ Prelude.enumFromTo f to
251+
252+enumerateFromIntegralBounded :: Property
253+enumerateFromIntegralBounded =
254+ property
255+ $ \f ->
256+ let unf = UF.take 50 UF.enumerateFromIntegralBounded
257+ in testUnfold unf (f :: Int) $
258+ Prelude.take 50 $ Prelude.enumFrom f
259+
260+enumerateFromThenIntegralBounded :: Property
261+enumerateFromThenIntegralBounded =
262+ property
263+ $ \f th ->
264+ let unf = UF.take 50 UF.enumerateFromThenIntegralBounded
265+ in testUnfold unf (f :: Int, th) $
266+ Prelude.take 50 $ Prelude.enumFromThen f th
267+
268+enumerateFromToIntegralBounded :: Property
269+enumerateFromToIntegralBounded =
270+ property
271+ $ \f to ->
272+ let unf = UF.take 50 UF.enumerateFromToIntegralBounded
273+ in testUnfold unf (f :: Int, to) $
274+ Prelude.take 50 $ Prelude.enumFromTo f to
275+
276+enumerateFromThenToIntegralBounded :: Property
277+enumerateFromThenToIntegralBounded =
278+ property
279+ $ \f th to ->
280+ let unf = UF.take 50 UF.enumerateFromThenToIntegralBounded
281+ in testUnfold unf (f :: Int, th, to) $
282+ Prelude.take 50 $ Prelude.enumFromThenTo f th to
283+
284+enumerateFromSmall :: Property
285+enumerateFromSmall =
286+ property
287+ $ \f ->
288+ let unf = UF.take 50 UF.enumerateFromSmall
289+ in testUnfold unf (f :: Char) $
290+ Prelude.take 50 $ Prelude.enumFrom f
291+
292+enumerateFromThenSmall :: Property
293+enumerateFromThenSmall =
294+ property
295+ $ \f th ->
296+ let unf = UF.take 50 UF.enumerateFromThenSmall
297+ in testUnfold unf (f :: Char, th) $
298+ Prelude.take 50 $ Prelude.enumFromThen f th
299+
300+enumerateFromToSmall :: Property
301+enumerateFromToSmall =
302+ property
303+ $ \f to ->
304+ let unf = UF.take 50 UF.enumerateFromToSmall
305+ in testUnfold unf (f :: Char, to) $
306+ Prelude.take 50 $ Prelude.enumFromTo f to
307+
308+enumerateFromThenToSmall :: Property
309+enumerateFromThenToSmall =
310+ property
311+ $ \f th to ->
312+ let unf = UF.take 50 UF.enumerateFromThenToSmall
313+ in testUnfold unf (f :: Char, th, to) $
314+ Prelude.take 50 $ Prelude.enumFromThenTo f th to
315+
316+enumerateFromSmallOrd :: Property
317+enumerateFromSmallOrd =
318+ property
319+ $ \f ->
320+ let unf = UF.take 3 UF.enumerateFromSmall
321+ in testUnfold unf (f :: Ordering) $
322+ Prelude.take 3 $ Prelude.enumFrom f
323+
324+enumerateFromThenSmallOrd :: Property
325+enumerateFromThenSmallOrd =
326+ property
327+ $ \f th ->
328+ let unf = UF.take 3 UF.enumerateFromThenSmall
329+ in testUnfold unf (f :: Ordering, th) $
330+ Prelude.take 3 $ Prelude.enumFromThen f th
331+
332+enumerateFromToSmallOrd :: Property
333+enumerateFromToSmallOrd =
334+ property
335+ $ \f to ->
336+ let unf = UF.take 3 UF.enumerateFromToSmall
337+ in testUnfold unf (f :: Ordering, to) $
338+ Prelude.take 3 $ Prelude.enumFromTo f to
339+
340+enumerateFromThenToSmallOrd :: Property
341+enumerateFromThenToSmallOrd =
342+ property
343+ $ \f th to ->
344+ let unf = UF.take 3 UF.enumerateFromThenToSmall
345+ in testUnfold unf (f :: Ordering, th, to) $
346+ Prelude.take 3 $ Prelude.enumFromThenTo f th to
347+
348+-------------------------------------------------------------------------------
349+enumerateFromSmallBool :: Property
350+enumerateFromSmallBool =
351+ property
352+ $ \f ->
353+ let unf = UF.take 2 UF.enumerateFromSmall
354+ in testUnfold unf (f :: Bool) $
355+ Prelude.take 2 $ Prelude.enumFrom f
356+
357+enumerateFromThenSmallBool :: Property
358+enumerateFromThenSmallBool =
359+ property
360+ $ \f th ->
361+ let unf = UF.take 2 UF.enumerateFromThenSmall
362+ in testUnfold unf (f :: Bool, th) $
363+ Prelude.take 2 $ Prelude.enumFromThen f th
364+
365+enumerateFromToSmallBool :: Property
366+enumerateFromToSmallBool =
367+ property
368+ $ \f to ->
369+ let unf = UF.take 2 UF.enumerateFromToSmall
370+ in testUnfold unf (f :: Bool, to) $
371+ Prelude.take 2 $ Prelude.enumFromTo f to
372+
373+enumerateFromThenToSmallBool :: Property
374+enumerateFromThenToSmallBool =
375+ property
376+ $ \f th to ->
377+ let unf = UF.take 2 UF.enumerateFromThenToSmall
378+ in testUnfold unf (f :: Bool, th, to) $
379+ Prelude.take 2 $ Prelude.enumFromThenTo f th to
380+-------------------------------------------------------------------------------
381+enumerateFromSmallUnit :: Property
382+enumerateFromSmallUnit =
383+ property
384+ $ \f ->
385+ let unf = UF.take 1 UF.enumerateFromSmall
386+ in testUnfold unf (f :: ()) $
387+ Prelude.take 1 $ Prelude.enumFrom f
388+
389+enumerateFromThenSmallUnit :: Property
390+enumerateFromThenSmallUnit =
391+ property
392+ $ \f th ->
393+ let unf = UF.take 1 UF.enumerateFromThenSmall
394+ in testUnfold unf (f :: (), th) $
395+ Prelude.take 1 $ Prelude.enumFromThen f th
396+
397+enumerateFromToSmallUnit :: Property
398+enumerateFromToSmallUnit =
399+ property
400+ $ \f to ->
401+ let unf = UF.take 1 UF.enumerateFromToSmall
402+ in testUnfold unf (f :: (), to) $
403+ Prelude.take 1 $ Prelude.enumFromTo f to
404+
405+enumerateFromThenToSmallUnit :: Property
406+enumerateFromThenToSmallUnit =
407+ property
408+ $ \f th to ->
409+ let unf = UF.take 1 UF.enumerateFromThenToSmall
410+ in testUnfold unf (f :: (), th, to) $
411+ Prelude.take 1 $ Prelude.enumFromThenTo f th to
412+
413+
414+#if MIN_VERSION_base(4,12,0)
415+enumerateFromFractional :: Property
416+enumerateFromFractional =
417+ property
418+ $ \f ->
419+ let unf = UF.take 50 UF.enumerateFromFractional
420+ in testUnfold unf (f :: Double) $
421+ Prelude.take 50 $ Prelude.enumFrom f
422+
423+enumerateFromThenFractional :: Property
424+enumerateFromThenFractional =
425+ property
426+ $ \f th ->
427+ let unf = UF.take 50 UF.enumerateFromThenFractional
428+ in testUnfold unf (f :: Double, th) $
429+ Prelude.take 50 $ Prelude.enumFromThen f th
430+
431+enumerateFromThenToFractional :: Property
432+enumerateFromThenToFractional =
433+ property
434+ $ \f th to ->
435+ let unf = UF.take 50 UF.enumerateFromThenToFractional
436+ in testUnfold unf (f :: Double, th, to) $
437+ Prelude.take 50 $ Prelude.enumFromThenTo f th to
438+
439+enumerateFromToFractional :: Property
440+enumerateFromToFractional =
225441 property
226442 $ \f t ->
227− let unf = UF.enumerateFromToIntegral t
228− in testUnfoldD unf f [f .. t]
443+ let unf = UF.enumerateFromToFractional
444+ in testUnfold unf (f :: Double, t) [f..(t :: Double)]
445+
446+#endif
229447
230448-------------------------------------------------------------------------------
231449-- Stream transformation
@@ -315,29 +533,29 @@ zipWithM :: Property
315533zipWithM =
316534 property
317535 $ \f ->
318− let unf1 = UF.enumerateFromToIntegral 10
319− unf2 = UF.enumerateFromToIntegral 20
320− fA = applyFun2 f :: Int -> Int -> Int
321− fM a b = modify (+ 1) >> return (fA a b)
322− unf = UF.zipWithM fM (UF.lmap fst unf1) (UF.lmap snd unf2)
323− lst = Prelude.zipWith fA [1 .. 10] [1 .. 20]
324− in testUnfoldMD unf (1, 1) 0 10 lst
536+ let unf1 = UF.enumerateFromToIntegral
537+ unf2 = UF.enumerateFromToIntegral
538+ fA = applyFun2 f :: Int -> Int -> Int
539+ fM a b = modify (+ 1) >> return (fA a b)
540+ unf = UF.zipWithM fM (UF.lmap fst unf1) (UF.lmap snd unf2)
541+ lst = Prelude.zipWith fA [1 .. 10] [1 .. 20]
542+ in testUnfoldMD unf ((1,10), (1,20)) 0 10 lst
325543
326544concat :: Bool
327545concat =
328546 let unfIn = UF.replicateM 10
329− unfOut = UF.map return $ UF.enumerateFromToIntegral 10
547+ unfOut = UF.map return UF.enumerateFromToIntegral
330548 unf = UF.many unfOut unfIn
331549 lst = Prelude.concat $ Prelude.map (Prelude.replicate 10) [1 .. 10]
332− in testUnfoldD unf 1 lst
550+ in testUnfoldD unf (1, 10) lst
333551
334552outerProduct :: Bool
335553outerProduct =
336− let unf1 = UF.enumerateFromToIntegral 10
337− unf2 = UF.enumerateFromToIntegral 20
554+ let unf1 = UF.enumerateFromToIntegral
555+ unf2 = UF.enumerateFromToIntegral
338556 unf = crossProduct unf1 unf2
339557 lst = [(a, b) :: (Int, Int) | a <- [0 .. 10], b <- [0 .. 20]]
340− in testUnfold unf ((0, 0) :: (Int, Int)) lst
558+ in testUnfold unf (((0,10) ,(0,20)) :: ((Int, Int), (Int, Int))) lst
341559
342560 where
343561
@@ -348,9 +566,9 @@ concatMapM =
348566 let inner b =
349567 let u = UF.lmap (\_ -> modify (+ 1) >> return b) (UF.replicateM 10)
350568 in modify (+ 1) >> return u
351− unf = UF.concatMapM inner (UF.enumerateFromToIntegral 10)
569+ unf = UF.concatMapM inner UF.enumerateFromToIntegral
352570 list = List.concatMap (replicate 10) [1 .. 10]
353− in testUnfoldMD unf 1 0 110 list
571+ in testUnfoldMD unf (1, 10) 0 110 list
354572
355573-------------------------------------------------------------------------------
356574-- Test groups
@@ -391,13 +609,45 @@ testGeneration =
391609 prop "repeatM" repeatM
392610 prop "iterateM" iterateM
393611 prop "fromIndicesM" fromIndicesM
394− prop "enumerateFromStepIntegral" enumerateFromStepIntegral
612+ ----------- Enumerate from Num ------------------------------------
613+ prop "enumerateFromNum" enumerateFromNum
614+ prop "enumerateFromThenNum" enumerateFromThenNum
615+ ----------- Enumerate from Integral -------------------------------
616+ prop "enumerateFromIntegral" enumerateFromIntegral
617+ prop "enumerateFromThenIntegral" enumerateFromThenIntegral
395618 prop "enumerateFromToIntegral" enumerateFromToIntegral
396− -- prop "enumerateFromIntegral" enumerateFromIntegral
397− prop "enumerateFromStepNum" enumerateFromStepNum
398− -- prop "numFrom" numFrom
619+ prop "enumerateFromThenToIntegral" enumerateFromThenToIntegral
620+
621+ prop "enumerateFromIntegralBounded" enumerateFromIntegralBounded
622+ prop "enumerateFromThenIntegralBounded" enumerateFromThenIntegralBounded
623+ prop "enumerateFromToIntegralBounded" enumerateFromToIntegralBounded
624+ prop "enumerateFromThenToIntegralBounded" enumerateFromThenToIntegralBounded
625+ ----------- Enumerate from Small Integral -------------------------
626+ prop "enumerateFromSmall" enumerateFromSmall
627+ prop "enumerateFromThenSmall" enumerateFromThenSmall
628+ prop "enumerateFromToSmall" enumerateFromToSmall
629+ prop "enumerateFromThenToSmall" enumerateFromThenToSmall
630+ --
631+ prop "enumerateFromSmallOrd" enumerateFromSmallOrd
632+ prop "enumerateFromThenSmallOrd" enumerateFromThenSmallOrd
633+ prop "enumerateFromToSmallOrd" enumerateFromToSmallOrd
634+ prop "enumerateFromThenToSmallOrd" enumerateFromThenToSmallOrd
635+
636+ prop "enumerateFromSmallUnit" enumerateFromSmallUnit
637+ prop "enumerateFromThenSmallUnit" enumerateFromThenSmallUnit
638+ prop "enumerateFromToSmallUnit" enumerateFromToSmallUnit
639+ prop "enumerateFromThenToSmallUnit" enumerateFromThenToSmallUnit
640+
641+ prop "enumerateFromSmallUnit" enumerateFromSmallBool
642+ prop "enumerateFromThenSmallBool" enumerateFromThenSmallBool
643+ prop "enumerateFromToSmallBool" enumerateFromToSmallBool
644+ prop "enumerateFromThenToSmallBool" enumerateFromThenToSmallBool
645+
399646#if MIN_VERSION_base(4,12,0)
647+ prop "enumerateFromFractional" enumerateFromFractional
648+ prop "enumerateFromThenFractional" enumerateFromThenFractional
400649 prop "enumerateFromToFractional" enumerateFromToFractional
650+ prop "enumerateFromThenToFractional" enumerateFromThenToFractional
401651#endif
402652
403653testTransformation :: Spec
test/Streamly/Test/Prelude/Serial.hs+2−2
@@ -449,7 +449,7 @@ unfold :: Property
449449unfold = monadicIO $ do
450450 a <- pick $ choose (0, max_length `div` 2)
451451 b <- pick $ choose (0, max_length)
452− let unf = UF.enumerateFromToIntegral b
452+ let unf = UF.supplySecond b UF.enumerateFromToIntegral
453453 ls <- S.toList $ S.unfold unf a
454454 return $ ls == [a..b]
455455
@@ -457,7 +457,7 @@ unfold0 :: Property
457457unfold0 = monadicIO $ do
458458 a <- pick $ choose (0, max_length `div` 2)
459459 b <- pick $ choose (0, max_length)
460− let unf = UF.supply a (UF.enumerateFromToIntegral b)
460+ let unf = UF.supply a (UF.supplySecond b UF.enumerateFromToIntegral)
461461 ls <- S.toList $ IS.unfold0 unf
462462 return $ ls == [a..b]
463463