on master help sign in
Change signature of enumerate functions
ba9a4e8Ranjeet Kumar Ranjan
benchmark/Streamly/Benchmark/Data/Unfold.hs+24−17
@@ -54,7 +54,7 @@ benchIO name f = bench name $ nfIO $ randomRIO (1,1) >>= f
54-- generate numbers up to the argument value
54-- generate numbers up to the argument value
55{-# INLINE source #-}
55{-# INLINE source #-}
56source :: Monad m => Int -> Unfold m Int Int
56source :: Monad m => Int -> Unfold m Int Int
57−source n = UF.enumerateFromToIntegral n
57+source n = UF.supplySecond n UF.enumerateFromToIntegral
58
58
59-------------------------------------------------------------------------------
59-------------------------------------------------------------------------------
60-- Benchmark helpers
60-- Benchmark helpers
@@ -73,7 +73,7 @@ drainTransformation unf f seed = drainGeneration (f unf) seed
73drainTransformationDefault ::
73drainTransformationDefault ::
74 Monad m => Int -> (Unfold m Int Int -> Unfold m c d) -> c -> m ()
74 Monad m => Int -> (Unfold m Int Int -> Unfold m c d) -> c -> m ()
75drainTransformationDefault to =
75drainTransformationDefault to =
76− drainTransformation (UF.enumerateFromToIntegral to)
76+ drainTransformation (UF.supplySecond to UF.enumerateFromToIntegral)
77
77
78{-# INLINE drainProduct #-}
78{-# INLINE drainProduct #-}
79drainProduct ::
79drainProduct ::
@@ -96,7 +96,7 @@ drainProductDefault to = drainProduct src src
96
96
97 where
97 where
98
98
99− src = UF.enumerateFromToIntegral to
99+ src = UF.supplySecond to UF.enumerateFromToIntegral
100
100
101-------------------------------------------------------------------------------
101-------------------------------------------------------------------------------
102-- Operations on input
102-- Operations on input
@@ -122,7 +122,7 @@ supply size start =
122supplyFirst :: Monad m => Int -> Int -> m ()
122supplyFirst :: Monad m => Int -> Int -> m ()
123supplyFirst size start =
123supplyFirst size start =
124 drainTransformation
124 drainTransformation
125− (UF.take size UF.enumerateFromStepIntegral)
125+ (UF.take size UF.enumerateFromThenIntegral)
126 (UF.supplyFirst start)
126 (UF.supplyFirst start)
127 1
127 1
128
128
@@ -130,7 +130,7 @@ supplyFirst size start =
130supplySecond :: Monad m => Int -> Int -> m ()
130supplySecond :: Monad m => Int -> Int -> m ()
131supplySecond size start =
131supplySecond size start =
132 drainTransformation
132 drainTransformation
133− (UF.take size UF.enumerateFromStepIntegral)
133+ (UF.take size UF.enumerateFromThenIntegral)
134 (UF.supplySecond 1)
134 (UF.supplySecond 1)
135 start
135 start
136
136
@@ -148,7 +148,7 @@ discardSecond size start =
148swap :: Monad m => Int -> Int -> m ()
148swap :: Monad m => Int -> Int -> m ()
149swap size start =
149swap size start =
150 drainTransformation
150 drainTransformation
151− (UF.take size UF.enumerateFromStepIntegral)
151+ (UF.take size UF.enumerateFromThenIntegral)
152 UF.swap
152 UF.swap
153 (1, start)
153 (1, start)
154
154
@@ -245,15 +245,19 @@ fromIndicesM :: Monad m => Int -> Int -> m ()
245fromIndicesM size start =
245fromIndicesM size start =
246 drainGeneration (UF.take size (UF.fromIndicesM return)) start
246 drainGeneration (UF.take size (UF.fromIndicesM return)) start
247
247
248−{-# INLINE enumerateFromStepIntegral #-}
248+{-# INLINE enumerateFromThenIntegral #-}
249−enumerateFromStepIntegral :: Monad m => Int -> Int -> m ()
249+enumerateFromThenIntegral :: Monad m => Int -> Int -> m ()
250−enumerateFromStepIntegral size start =
250+enumerateFromThenIntegral size start =
251− drainGeneration (UF.take size UF.enumerateFromStepIntegral) (start, 1)
251+ drainGeneration (UF.take size UF.enumerateFromThenIntegral) (start, 1)
252
252
253{-# INLINE enumerateFromToIntegral #-}
253{-# INLINE enumerateFromToIntegral #-}
254enumerateFromToIntegral :: Monad m => Int -> Int -> m ()
254enumerateFromToIntegral :: Monad m => Int -> Int -> m ()
255enumerateFromToIntegral size start =
255enumerateFromToIntegral size start =
256− drainGeneration (UF.enumerateFromToIntegral (size + start)) start
256+ drainGeneration
257+ ( UF.supplySecond
258+ (size + start)
259+ UF.enumerateFromToIntegral
260+ ) start
257
261
258{-# INLINE enumerateFromIntegral #-}
262{-# INLINE enumerateFromIntegral #-}
259enumerateFromIntegral :: Monad m => Int -> Int -> m ()
263enumerateFromIntegral :: Monad m => Int -> Int -> m ()
@@ -263,18 +267,21 @@ enumerateFromIntegral size start =
263{-# INLINE enumerateFromStepNum #-}
267{-# INLINE enumerateFromStepNum #-}
264enumerateFromStepNum :: Monad m => Int -> Int -> m ()
268enumerateFromStepNum :: Monad m => Int -> Int -> m ()
265enumerateFromStepNum size start =
269enumerateFromStepNum size start =
266− drainGeneration (UF.take size (UF.enumerateFromStepNum 1)) start
270+ drainGeneration (UF.take size (UF.enumerateFromThenNum)) (start, 1)
267
271
268{-# INLINE numFrom #-}
272{-# INLINE numFrom #-}
269numFrom :: Monad m => Int -> Int -> m ()
273numFrom :: 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
271
275
272{-# INLINE enumerateFromToFractional #-}
276{-# INLINE enumerateFromToFractional #-}
273enumerateFromToFractional :: Monad m => Int -> Int -> m ()
277enumerateFromToFractional :: Monad m => Int -> Int -> m ()
274enumerateFromToFractional size start =
278enumerateFromToFractional size start =
275 let intToDouble x = (fromInteger (fromIntegral x)) :: Double
279 let intToDouble x = (fromInteger (fromIntegral x)) :: Double
276 in drainGeneration
280 in drainGeneration
281+ ( UF.supplySecond
277− (UF.enumerateFromToFractional (intToDouble $ start + size))
282+ (intToDouble $ start + size)
283+ UF.enumerateFromToFractional
284+ )
278 (intToDouble start)
285 (intToDouble start)
279
286
280-------------------------------------------------------------------------------
287-------------------------------------------------------------------------------
@@ -434,8 +441,8 @@ concatMapM value start =
434 where
441 where
435
442
436 val = nthRoot 2 value
443 val = nthRoot 2 value
437− unfoldInGen i = return (UF.enumerateFromToIntegral (i + val))
444+ unfoldInGen i = return (UF.supplySecond (i + val) UF.enumerateFromToIntegral)
438− unfoldOut = UF.enumerateFromToIntegral (start + val)
445+ unfoldOut = UF.supplySecond (start + val) UF.enumerateFromToIntegral
439
446
440{-# INLINE toNull #-}
447{-# INLINE toNull #-}
441toNull :: Monad m => Int -> Int -> m ()
448toNull :: Monad m => Int -> Int -> m ()
@@ -638,7 +645,7 @@ o_1_space_generation size =
638 , benchIO "repeatM" $ repeatM size
645 , benchIO "repeatM" $ repeatM size
639 , benchIO "iterateM" $ iterateM size
646 , benchIO "iterateM" $ iterateM size
640 , benchIO "fromIndicesM" $ fromIndicesM size
647 , benchIO "fromIndicesM" $ fromIndicesM size
641− , benchIO "enumerateFromStepIntegral" $ enumerateFromStepIntegral size
648+ , benchIO "enumerateFromThenIntegral" $ enumerateFromThenIntegral size
642 , benchIO "enumerateFromToIntegral" $ enumerateFromToIntegral size
649 , benchIO "enumerateFromToIntegral" $ enumerateFromToIntegral size
643 , benchIO "enumerateFromIntegral" $ enumerateFromIntegral size
650 , benchIO "enumerateFromIntegral" $ enumerateFromIntegral size
644 , benchIO "enumerateFromStepNum" $ enumerateFromStepNum size
651 , benchIO "enumerateFromStepNum" $ enumerateFromStepNum size
src/Streamly/Internal/Data/Unfold.hs+25−144
@@ -142,19 +142,34 @@ module Streamly.Internal.Data.Unfold
142
142
143 -- ** Enumerations
143 -- ** Enumerations
144 , Enumerable (..)
144 , Enumerable (..)
145− -- *** Enumerate Num
146− , enumerateFromStepNum
147− , numFrom
148
145
149− -- *** Enumerate Integral
146+ -- ** Enumerate Num
150− , enumerateFromStepIntegral
147+ , enumerateFromNum
151− , enumerateFromToIntegral
148+ , enumerateFromThenNum
149+
150+ -- ** Enumerating 'Bounded 'Integral' Types
151+ , enumerateFromIntegralBounded
152+ , enumerateFromThenIntegralBounded
153+ , enumerateFromToIntegralBounded
154+ , enumerateFromThenToIntegralBounded
155+
156+ -- ** Enumerating 'Unounded Integral' Types
152 , enumerateFromIntegral
157 , enumerateFromIntegral
158+ , enumerateFromThenIntegral
159+ , enumerateFromToIntegral
160+ , enumerateFromThenToIntegral
161+
162+ -- ** Enumerating 'Small Integral' Types
163+ , enumerateFromSmall
164+ , enumerateFromThenSmall
165+ , enumerateFromToSmall
166+ , enumerateFromThenToSmall
153
167
154− -- *** Enumerate Fractional
168+ -- ** Enumerating 'Fractional' Types
155− -- | Use 'Num' enumerations for fractional or floating point number
169+ , enumerateFromFractional
156− -- enumerations.
170+ , enumerateFromThenFractional
157 , enumerateFromToFractional
171 , enumerateFromToFractional
172+ , enumerateFromThenToFractional
158
173
159 -- ** From Containers
174 -- ** From Containers
160 , fromList
175 , fromList
@@ -230,20 +245,16 @@ module Streamly.Internal.Data.Unfold
230 )
245 )
231where
246where
232
247
233−import Control.Exception (Exception, fromException, mask_)
248+import Control.Exception (Exception, mask_)
234−import Control.Monad ((>=>), when)
235import Control.Monad.Catch (MonadCatch)
249import Control.Monad.Catch (MonadCatch)
236import Control.Monad.IO.Class (MonadIO(..))
250import Control.Monad.IO.Class (MonadIO(..))
237import Control.Monad.Trans.Control (MonadBaseControl, liftBaseOp_)
251import Control.Monad.Trans.Control (MonadBaseControl, liftBaseOp_)
238−import Data.IORef (newIORef, readIORef, mkWeakIORef, writeIORef)
239−import Data.Maybe (isNothing)
240import GHC.Types (SPEC(..))
252import GHC.Types (SPEC(..))
241import Streamly.Internal.Control.Concurrent (MonadAsync)
253import Streamly.Internal.Control.Concurrent (MonadAsync)
242import Streamly.Internal.Data.Fold.Type (Fold(..))
254import Streamly.Internal.Data.Fold.Type (Fold(..))
243import Streamly.Internal.Data.IOFinalizer
255import Streamly.Internal.Data.IOFinalizer
244 (newIOFinalizer, runIOFinalizer, clearingIOFinalizer)
256 (newIOFinalizer, runIOFinalizer, clearingIOFinalizer)
245import Streamly.Internal.Data.Stream.StreamD.Type (Stream(..), Step(..))
257import Streamly.Internal.Data.Stream.StreamD.Type (Stream(..), Step(..))
246−import Streamly.Internal.Data.SVar.Type (defState)
247
258
248import qualified Control.Monad.Catch as MC
259import qualified Control.Monad.Catch as MC
249import qualified Data.Tuple as Tuple
260import qualified Data.Tuple as Tuple
@@ -252,7 +263,6 @@ import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
252import qualified Streamly.Internal.Data.Stream.StreamK as K (uncons)
263import qualified Streamly.Internal.Data.Stream.StreamK as K (uncons)
253import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
264import qualified Streamly.Internal.Data.Stream.StreamK.Type as K
254
265
255−import Streamly.Internal.Data.Unfold.Type
256import Streamly.Internal.Data.SVar
266import Streamly.Internal.Data.SVar
257import Streamly.Internal.Data.Unfold.Enumeration
267import Streamly.Internal.Data.Unfold.Enumeration
258import Streamly.Internal.Data.Unfold.Type
268import Streamly.Internal.Data.Unfold.Type
@@ -733,135 +743,6 @@ dropWhileM f (Unfold step inject) = Unfold step' inject'
733dropWhile :: Monad m => (b -> Bool) -> Unfold m a b -> Unfold m a b
743dropWhile :: Monad m => (b -> Bool) -> Unfold m a b -> Unfold m a b
734dropWhile f = dropWhileM (return . f)
744dropWhile f = dropWhileM (return . f)
735
745
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−
865------------------------------------------------------------------------------
746------------------------------------------------------------------------------
866-- Exceptions
747-- Exceptions
867------------------------------------------------------------------------------
748------------------------------------------------------------------------------
src/Streamly/Internal/Data/Unfold/Enumeration.hs+371−82
@@ -23,32 +23,39 @@ module Streamly.Internal.Data.Unfold.Enumeration
23 (
23 (
24 Enumerable (..)
24 Enumerable (..)
25
25
26− -- ** Enumerate Num
26+ -- ** Enumerate 'Num' Types
27− , enumerateFromStepNum
27+ , enumerateFromNum
28− , numFrom
28+ , enumerateFromThenNum
29− , numFromThen
30
29
31− -- ** Enumerating 'Bounded' 'Integral' Types
30+ -- ** Enumerating 'Bounded Integral' Types
31+ , enumerateFromIntegralBounded
32+ , enumerateFromThenIntegralBounded
33+ , enumerateFromToIntegralBounded
34+ , enumerateFromThenToIntegralBounded
35+
36+ -- ** Enumerating 'Unbounded Integral' Types
32 , enumerateFromIntegral
37 , enumerateFromIntegral
33 , enumerateFromThenIntegral
38 , enumerateFromThenIntegral
34−
35− -- ** Enumerating 'Integral' Types
36 , enumerateFromToIntegral
39 , enumerateFromToIntegral
37 , enumerateFromThenToIntegral
40 , enumerateFromThenToIntegral
38
41
39− -- ** Enumerating unbounded 'Integral' Types
42+ -- ** Enumerating 'Small Integral' Types
40− , enumerateFromStepIntegral
43+ , enumerateFromSmall
44+ , enumerateFromThenSmall
45+ , enumerateFromToSmall
46+ , enumerateFromThenToSmall
41
47
42 -- ** Enumerating 'Fractional' Types
48 -- ** Enumerating 'Fractional' Types
43 , enumerateFromFractional
49 , enumerateFromFractional
44− , enumerateFromToFractional
45 , enumerateFromThenFractional
50 , enumerateFromThenFractional
51+ , enumerateFromToFractional
46 , enumerateFromThenToFractional
52 , enumerateFromThenToFractional
47 )
53 )
48where
54where
49
55
50#include "inline.hs"
56#include "inline.hs"
51import Data.Fixed
57import Data.Fixed
58+import Data.Bifunctor (bimap)
52import Data.Int
59import Data.Int
53import Data.Ratio
60import Data.Ratio
54import Data.Word
61import Data.Word
@@ -64,36 +71,102 @@ import Prelude
64-- Enumeration of Num
71-- Enumeration of Num
65------------------------------------------------------------------------------
72------------------------------------------------------------------------------
66
73
67−-- | Generate an infinite stream starting from a starting value with increments
74+-- | Generate an infinite stream starting from a starting value with default
68−-- of the given stride. The implementation is numerically stable for floating
75+-- stride of value 1. The implementation is numerically stable for floating
69-- point values.
76-- point values.
70--
77--
71-- Note 'enumerateFromStepIntegral' is faster for integrals.
78-- Note 'enumerateFromStepIntegral' is faster for integrals.
72--
79--
73-- /Pre-release/
80-- /Pre-release/
74--
81--
75−{-# INLINE enumerateFromStepNum #-}
82+{-# INLINE enumerateFromNum #-}
76−enumerateFromStepNum :: (Monad m, Num a) => a -> Unfold m a a
83+enumerateFromNum :: (Monad m, Num a) => Unfold m a a
77−enumerateFromStepNum stride = Unfold step inject
84+enumerateFromNum = Unfold step inject
78
85
79 where
86 where
80
87
81− inject !from = return (from, 0)
88+ inject !from = return (from, 1, 0)
82
89
83 {-# INLINE_LATE step #-}
90 {-# INLINE_LATE step #-}
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 $
84− step (from, !i) = return $ (Yield $! (from + i * stride)) $! (from, i + 1)
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)
85
132
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.
87--
153--
88-- /Pre-release/
154-- /Pre-release/
89--
155--
90−{-# INLINE_NORMAL numFrom #-}
156+{-# INLINE enumerateFromToNumBounded #-}
157+enumerateFromToNumBounded :: (Monad m, Ord a, Fractional a) =>
91−numFrom :: (Monad m, Num a) => Unfold m a a
158+ Unfold m (a, a) a
92−numFrom = enumerateFromStepNum 1
159+enumerateFromToNumBounded = Unfold step inject
160+
161+ where
93
162
94−{-# INLINE_NORMAL numFromThen #-}
163+ inject (!from, !to) = return (from, 1, to, 0)
95−numFromThen :: (Monad m, Num a) => a -> Unfold m a a
164+
96−numFromThen = enumerateFromStepNum
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
97
170
98------------------------------------------------------------------------------
171------------------------------------------------------------------------------
99-- Enumeration of Integrals
172-- Enumeration of Integrals
@@ -105,55 +178,159 @@ numFromThen = enumerateFromStepNum
105enumerateFromStepIntegral :: (Integral a, Monad m) => Unfold m (a, a) a
178enumerateFromStepIntegral :: (Integral a, Monad m) => Unfold m (a, a) a
106enumerateFromStepIntegral = Unfold step inject
179enumerateFromStepIntegral = Unfold step inject
107 where
180 where
108− inject (from, stride) = from `seq` stride `seq` return (from, stride)
181+ inject (from, next) = from `seq` next `seq` return (from, next - from)
109 {-# INLINE_LATE step #-}
182 {-# INLINE_LATE step #-}
110 step (x, stride) = return $ Yield x $! (x + stride, stride)
183 step (x, stride) = return $ Yield x $! (x + stride, stride)
111
184
112−-- We are assuming that "to" is constrained by the type to be within
185+-- | Can be used to enumerate bounded integrals from starting from with
113−-- max/min bounds.
186+-- stride of (next-from) . This check for overflow or underflow for
114−{-# INLINE enumerateFromToIntegral #-}
187+-- bounded integrals.
115−enumerateFromToIntegral :: (Monad m, Integral a) => a -> Unfold m a a
188+-- /Pre-release/
116−enumerateFromToIntegral to =
189+--
117− takeWhile (<= to) $ supplySecond 1 enumerateFromStepIntegral
190+{-# INLINE_NORMAL enumerateFromStepIntegralBounded #-}
118−
191+enumerateFromStepIntegralBounded ::
119−{-# INLINE enumerateFromThenToIntegral #-}
192+ forall a m. (Integral a, Bounded a, Monad m) =>
120−enumerateFromThenToIntegral :: (Monad m, Integral a) => a -> a -> Unfold m a a
193+ Unfold m (a, a) a
121−enumerateFromThenToIntegral stride to =
194+enumerateFromStepIntegralBounded = Unfold step inject
122− takeWhile (<= to) $ supplySecond stride enumerateFromStepIntegral
195+ where
123−
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 ----------------------------------------------
124{-# INLINE enumerateFromIntegral #-}
274{-# INLINE enumerateFromIntegral #-}
125−enumerateFromIntegral :: (Monad m, Integral a, Bounded a) => Unfold m a a
275+enumerateFromIntegral :: (Monad m, Integral a) => Unfold m a a
126−enumerateFromIntegral = enumerateFromToIntegral maxBound
276+enumerateFromIntegral = supplyNextFromStride (+ 1) enumerateFromStepIntegral
127
277
128{-# INLINE enumerateFromThenIntegral #-}
278{-# INLINE enumerateFromThenIntegral #-}
129−enumerateFromThenIntegral :: (Monad m, Integral a, Bounded a) => a -> Unfold m a a
279+enumerateFromThenIntegral :: (Monad m, Integral a ) => Unfold m (a, a) a
130−enumerateFromThenIntegral stride = enumerateFromThenToIntegral stride maxBound
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
131
312
132------------------------------------------------------------------------------
313------------------------------------------------------------------------------
133-- Enumeration of Fractionals
314-- Enumeration of Fractionals
134------------------------------------------------------------------------------
315------------------------------------------------------------------------------
135
316
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−
145{-# INLINE_NORMAL enumerateFromFractional #-}
317{-# INLINE_NORMAL enumerateFromFractional #-}
146enumerateFromFractional :: (Monad m, Fractional a) => Unfold m a a
318enumerateFromFractional :: (Monad m, Fractional a) => Unfold m a a
147−enumerateFromFractional = enumerateFromStepNum 1
319+enumerateFromFractional = enumerateFromNum
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
153
320
154{-# INLINE_NORMAL enumerateFromThenFractional #-}
321{-# INLINE_NORMAL enumerateFromThenFractional #-}
155−enumerateFromThenFractional :: (Monad m, Fractional a) => a -> Unfold m a a
322+enumerateFromThenFractional :: (Monad m, Fractional a) => Unfold m (a, a) a
156−enumerateFromThenFractional = enumerateFromStepNum
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
157
334
158-------------------------------------------------------------------------------
335-------------------------------------------------------------------------------
159-- Enumerable type class
336-- Enumerable type class
@@ -212,7 +389,7 @@ class Enum a => Enumerable a where
212-- @
389-- @
213--
390--
214-- /Pre-release/
391-- /Pre-release/
215− enumerateFromTo :: Monad m => a -> Unfold m a a
392+ enumerateFromTo :: Monad m => Unfold m (a, a) a
216
393
217-- @enumerateFromThen from then@ generates a stream whose first element
394-- @enumerateFromThen from then@ generates a stream whose first element
218-- is @from@ and the successive elements are
395-- is @from@ and the successive elements are
@@ -231,7 +408,7 @@ class Enum a => Enumerable a where
231-- @
408-- @
232--
409--
233-- /Pre-release/
410-- /Pre-release/
234− enumerateFromThen :: Monad m => a -> Unfold m a a
411+ enumerateFromThen :: Monad m => Unfold m (a, a) a
235
412
236-- @enumerateFromThenTo from then to@ generates a finite stream whose
413-- @enumerateFromThenTo from then to@ generates a finite stream whose
237-- first element is @from@ and the successive elements are in
414-- first element is @from@ and the successive elements are in
@@ -249,7 +426,112 @@ class Enum a => Enumerable a where
249-- @
426-- @
250--
427--
251-- /Pre-release/
428-- /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
253
535
254-------------------------------------------------------------------------------
536-------------------------------------------------------------------------------
255-- Enumerable Instances
537-- Enumerable Instances
@@ -259,13 +541,13 @@ class Enum a => Enumerable a where
259#define ENUMERABLE_BOUNDED_SMALL(SMALL_TYPE) \
541#define ENUMERABLE_BOUNDED_SMALL(SMALL_TYPE) \
260instance Enumerable SMALL_TYPE where { \
542instance Enumerable SMALL_TYPE where { \
261 {-# INLINE enumerateFrom #-}; \
543 {-# INLINE enumerateFrom #-}; \
262− enumerateFrom = undefined; \
544+ enumerateFrom = enumerateFromSmall; \
263 {-# INLINE enumerateFromThen #-}; \
545 {-# INLINE enumerateFromThen #-}; \
264− enumerateFromThen = undefined; \
546+ enumerateFromThen = enumerateFromThenSmall; \
265 {-# INLINE enumerateFromTo #-}; \
547 {-# INLINE enumerateFromTo #-}; \
266− enumerateFromTo = undefined; \
548+ enumerateFromTo = enumerateFromToSmall; \
267 {-# INLINE enumerateFromThenTo #-}; \
549 {-# INLINE enumerateFromThenTo #-}; \
268− enumerateFromThenTo = undefined }
550+ enumerateFromThenTo = enumerateFromThenToSmall }
269
551
270ENUMERABLE_BOUNDED_SMALL(())
552ENUMERABLE_BOUNDED_SMALL(())
271ENUMERABLE_BOUNDED_SMALL(Bool)
553ENUMERABLE_BOUNDED_SMALL(Bool)
@@ -273,16 +555,16 @@ ENUMERABLE_BOUNDED_SMALL(Ordering)
273ENUMERABLE_BOUNDED_SMALL(Char)
555ENUMERABLE_BOUNDED_SMALL(Char)
274
556
275-- For bounded Integral Enum types, may be larger than Int.
557-- For bounded Integral Enum types, may be larger than Int.
276−#define ENUMERABLE_BOUNDED_INTEGRAL(INTEGRAL_TYPE) \
558+#define ENUMERABLE_BOUNDED_INTEGRAL(INTEGRAL_TYPE) \
277−instance Enumerable INTEGRAL_TYPE where { \
559+instance Enumerable INTEGRAL_TYPE where { \
278− {-# INLINE enumerateFrom #-}; \
560+ {-# INLINE enumerateFrom #-}; \
279− enumerateFrom = enumerateFromIntegral; \
561+ enumerateFrom = enumerateFromIntegralBounded; \
280− {-# INLINE enumerateFromThen #-}; \
562+ {-# INLINE enumerateFromThen #-}; \
281− enumerateFromThen = enumerateFromThenIntegral; \
563+ enumerateFromThen = enumerateFromThenIntegralBounded; \
282− {-# INLINE enumerateFromTo #-}; \
564+ {-# INLINE enumerateFromTo #-}; \
283− enumerateFromTo = enumerateFromToIntegral; \
565+ enumerateFromTo = enumerateFromToIntegralBounded; \
284− {-# INLINE enumerateFromThenTo #-}; \
566+ {-# INLINE enumerateFromThenTo #-}; \
285− enumerateFromThenTo = enumerateFromThenToIntegral }
567+ enumerateFromThenTo = enumerateFromThenToIntegralBounded }
286
568
287ENUMERABLE_BOUNDED_INTEGRAL(Int)
569ENUMERABLE_BOUNDED_INTEGRAL(Int)
288ENUMERABLE_BOUNDED_INTEGRAL(Int8)
570ENUMERABLE_BOUNDED_INTEGRAL(Int8)
@@ -299,10 +581,9 @@ ENUMERABLE_BOUNDED_INTEGRAL(Word64)
299#define ENUMERABLE_UNBOUNDED_INTEGRAL(INTEGRAL_TYPE) \
581#define ENUMERABLE_UNBOUNDED_INTEGRAL(INTEGRAL_TYPE) \
300instance Enumerable INTEGRAL_TYPE where { \
582instance Enumerable INTEGRAL_TYPE where { \
301 {-# INLINE enumerateFrom #-}; \
583 {-# INLINE enumerateFrom #-}; \
302− enumerateFrom = supplySecond 1 enumerateFromStepIntegral; \
584+ enumerateFrom = enumerateFromIntegral; \
303 {-# INLINE enumerateFromThen #-}; \
585 {-# INLINE enumerateFromThen #-}; \
304− enumerateFromThen next = \
586+ enumerateFromThen = enumerateFromThenIntegral; \
305− lmap (\from -> (from, next - from)) enumerateFromStepIntegral; \
306 {-# INLINE enumerateFromTo #-}; \
587 {-# INLINE enumerateFromTo #-}; \
307 enumerateFromTo = enumerateFromToIntegral; \
588 enumerateFromTo = enumerateFromToIntegral; \
308 {-# INLINE enumerateFromThenTo #-}; \
589 {-# INLINE enumerateFromThenTo #-}; \
@@ -329,10 +610,18 @@ ENUMERABLE_FRACTIONAL((Ratio a),Integral a)
329
610
330instance Enumerable a => Enumerable (Identity a) where
611instance Enumerable a => Enumerable (Identity a) where
331 {-# INLINE enumerateFrom #-}
612 {-# INLINE enumerateFrom #-}
613+ enumerateFrom =
332− enumerateFrom = map Identity $ lmap runIdentity enumerateFrom
614+ map Identity $ lmap runIdentity enumerateFrom
333 {-# INLINE enumerateFromThen #-}
615 {-# INLINE enumerateFromThen #-}
334− enumerateFromThen = undefined
616+ enumerateFromThen =
617+ map Identity $ lmap (bimap runIdentity runIdentity) enumerateFromThen
335 {-# INLINE enumerateFromTo #-}
618 {-# INLINE enumerateFromTo #-}
336− enumerateFromTo = undefined
619+ enumerateFromTo =
620+ map Identity $ lmap (bimap runIdentity runIdentity) enumerateFromThen
337 {-# INLINE enumerateFromThenTo #-}
621 {-# 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
34 , map
34 , map
35 , supply
35 , supply
36 , supplyFirst
36 , supplyFirst
37− , supplySecond
37+ , supplySecond
38+ , supplyMiddle
39+ , supplySecondThird
40+ , supplyNextFromStride
38 , takeWhileM
41 , takeWhileM
39 , takeWhile
42 , takeWhile
40
43
@@ -218,6 +221,37 @@ supplyFirst a = lmap (a, )
218supplySecond :: b -> Unfold m (a, b) c -> Unfold m a c
221supplySecond :: b -> Unfold m (a, b) c -> Unfold m a c
219supplySecond b = lmap (, b)
222supplySecond b = lmap (, b)
220
223
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+
221------------------------------------------------------------------------------
255------------------------------------------------------------------------------
222-- Filter input
256-- Filter input
223------------------------------------------------------------------------------
257------------------------------------------------------------------------------
streamly.cabal+1−2
@@ -422,8 +422,7 @@ library
422 -- streamly-core
422 -- streamly-core
423 , Streamly.Internal.Data.Unfold
423 , Streamly.Internal.Data.Unfold
424 , Streamly.Internal.Data.Unfold.SVar
424 , Streamly.Internal.Data.Unfold.SVar
425− , Streamly.Internal.Data.Unfold.Enumeration
425+ , Streamly.Internal.Data.Unfold.Enumeration
426− , Streamly.Internal.Data.Unfold
427 , Streamly.Internal.Data.Fold.Tee
426 , Streamly.Internal.Data.Fold.Tee
428 , Streamly.Internal.Data.Fold
427 , Streamly.Internal.Data.Fold
429 , Streamly.Internal.Data.Fold.SVar
428 , Streamly.Internal.Data.Fold.SVar
test/Streamly/Test/Data/Unfold.hs+289−39
@@ -195,37 +195,255 @@ fromIndicesM =
195 unf = UF.take 100 $ UF.fromIndicesM indFM
195 unf = UF.take 100 $ UF.fromIndicesM indFM
196 in testUnfoldMD unf 1 0 (length list) list
196 in testUnfoldMD unf 1 0 (length list) list
197
197
198−enumerateFromStepNum :: Property
198+-------------------------------------------------------------------------------
199−enumerateFromStepNum =
199+-- Test for Num type -----------------------------------------------------
200+-------------------------------------------------------------------------------
201+enumerateFromNum :: Property
202+enumerateFromNum =
200 property
203 property
201− $ \f s ->
204+ $ \f ->
202− let unf = UF.take 10 $ UF.enumerateFromStepNum s
205+ let unf = UF.take 50 UF.enumerateFromNum
203− lst = Prelude.take 10 $ List.unfoldr (\x -> Just (x, x + s)) f
206+ in testUnfold unf (f :: Int) $
204− in testUnfoldD unf f lst
207+ Prelude.take 50 $ Prelude.enumFrom f
205
208
206−#if MIN_VERSION_base(4,12,0)
209+enumerateFromThenNum :: Property
207−enumerateFromToFractional :: Property
210+enumerateFromThenNum =
208−enumerateFromToFractional =
209 property
211 property
210− $ \f t ->
212+ $ \f th ->
211− let unf = UF.enumerateFromToFractional (t :: Double)
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
212− in testUnfold unf (f :: Double) [f..(t :: Double)]
225+ in testUnfold unf (f :: Integer) $
213−#endif
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
214
235
215−enumerateFromStepIntegral :: Property
236+enumerateFromThenToIntegral :: Property
216−enumerateFromStepIntegral =
237+enumerateFromThenToIntegral =
217 property
238 property
218− $ \f s ->
239+ $ \f th to ->
219− let unf = UF.take 10 UF.enumerateFromStepIntegral
240+ let unf = UF.take 50 UF.enumerateFromThenToIntegral
220− lst = Prelude.take 10 $ List.unfoldr (\x -> Just (x, x + s)) f
241+ in testUnfold unf (f :: Integer, th, to) $
221− in testUnfoldD unf (f, s) lst
242+ Prelude.take 50 $ Prelude.enumFromThenTo f th to
222
243
223enumerateFromToIntegral :: Property
244enumerateFromToIntegral :: Property
224enumerateFromToIntegral =
245enumerateFromToIntegral =
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 =
225 property
441 property
226 $ \f t ->
442 $ \f t ->
227− let unf = UF.enumerateFromToIntegral t
443+ let unf = UF.enumerateFromToFractional
228− in testUnfoldD unf f [f .. t]
444+ in testUnfold unf (f :: Double, t) [f..(t :: Double)]
445+
446+#endif
229
447
230-------------------------------------------------------------------------------
448-------------------------------------------------------------------------------
231-- Stream transformation
449-- Stream transformation
@@ -315,29 +533,29 @@ zipWithM :: Property
315zipWithM =
533zipWithM =
316 property
534 property
317 $ \f ->
535 $ \f ->
318− let unf1 = UF.enumerateFromToIntegral 10
536+ let unf1 = UF.enumerateFromToIntegral
319− unf2 = UF.enumerateFromToIntegral 20
537+ unf2 = UF.enumerateFromToIntegral
320− fA = applyFun2 f :: Int -> Int -> Int
538+ fA = applyFun2 f :: Int -> Int -> Int
321− fM a b = modify (+ 1) >> return (fA a b)
539+ fM a b = modify (+ 1) >> return (fA a b)
322− unf = UF.zipWithM fM (UF.lmap fst unf1) (UF.lmap snd unf2)
540+ unf = UF.zipWithM fM (UF.lmap fst unf1) (UF.lmap snd unf2)
323− lst = Prelude.zipWith fA [1 .. 10] [1 .. 20]
541+ lst = Prelude.zipWith fA [1 .. 10] [1 .. 20]
324− in testUnfoldMD unf (1, 1) 0 10 lst
542+ in testUnfoldMD unf ((1,10), (1,20)) 0 10 lst
325
543
326concat :: Bool
544concat :: Bool
327concat =
545concat =
328 let unfIn = UF.replicateM 10
546 let unfIn = UF.replicateM 10
329− unfOut = UF.map return $ UF.enumerateFromToIntegral 10
547+ unfOut = UF.map return UF.enumerateFromToIntegral
330 unf = UF.many unfOut unfIn
548 unf = UF.many unfOut unfIn
331 lst = Prelude.concat $ Prelude.map (Prelude.replicate 10) [1 .. 10]
549 lst = Prelude.concat $ Prelude.map (Prelude.replicate 10) [1 .. 10]
332− in testUnfoldD unf 1 lst
550+ in testUnfoldD unf (1, 10) lst
333
551
334outerProduct :: Bool
552outerProduct :: Bool
335outerProduct =
553outerProduct =
336− let unf1 = UF.enumerateFromToIntegral 10
554+ let unf1 = UF.enumerateFromToIntegral
337− unf2 = UF.enumerateFromToIntegral 20
555+ unf2 = UF.enumerateFromToIntegral
338 unf = crossProduct unf1 unf2
556 unf = crossProduct unf1 unf2
339 lst = [(a, b) :: (Int, Int) | a <- [0 .. 10], b <- [0 .. 20]]
557 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
341
559
342 where
560 where
343
561
@@ -348,9 +566,9 @@ concatMapM =
348 let inner b =
566 let inner b =
349 let u = UF.lmap (\_ -> modify (+ 1) >> return b) (UF.replicateM 10)
567 let u = UF.lmap (\_ -> modify (+ 1) >> return b) (UF.replicateM 10)
350 in modify (+ 1) >> return u
568 in modify (+ 1) >> return u
351− unf = UF.concatMapM inner (UF.enumerateFromToIntegral 10)
569+ unf = UF.concatMapM inner UF.enumerateFromToIntegral
352 list = List.concatMap (replicate 10) [1 .. 10]
570 list = List.concatMap (replicate 10) [1 .. 10]
353− in testUnfoldMD unf 1 0 110 list
571+ in testUnfoldMD unf (1, 10) 0 110 list
354
572
355-------------------------------------------------------------------------------
573-------------------------------------------------------------------------------
356-- Test groups
574-- Test groups
@@ -391,13 +609,45 @@ testGeneration =
391 prop "repeatM" repeatM
609 prop "repeatM" repeatM
392 prop "iterateM" iterateM
610 prop "iterateM" iterateM
393 prop "fromIndicesM" fromIndicesM
611 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
395 prop "enumerateFromToIntegral" enumerateFromToIntegral
618 prop "enumerateFromToIntegral" enumerateFromToIntegral
396− -- prop "enumerateFromIntegral" enumerateFromIntegral
619+ prop "enumerateFromThenToIntegral" enumerateFromThenToIntegral
397− prop "enumerateFromStepNum" enumerateFromStepNum
620+
398− -- prop "numFrom" numFrom
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+
399#if MIN_VERSION_base(4,12,0)
646#if MIN_VERSION_base(4,12,0)
647+ prop "enumerateFromFractional" enumerateFromFractional
648+ prop "enumerateFromThenFractional" enumerateFromThenFractional
400 prop "enumerateFromToFractional" enumerateFromToFractional
649 prop "enumerateFromToFractional" enumerateFromToFractional
650+ prop "enumerateFromThenToFractional" enumerateFromThenToFractional
401#endif
651#endif
402
652
403testTransformation :: Spec
653testTransformation :: Spec
test/Streamly/Test/Prelude/Serial.hs+2−2
@@ -449,7 +449,7 @@ unfold :: Property
449unfold = monadicIO $ do
449unfold = monadicIO $ do
450 a <- pick $ choose (0, max_length `div` 2)
450 a <- pick $ choose (0, max_length `div` 2)
451 b <- pick $ choose (0, max_length)
451 b <- pick $ choose (0, max_length)
452− let unf = UF.enumerateFromToIntegral b
452+ let unf = UF.supplySecond b UF.enumerateFromToIntegral
453 ls <- S.toList $ S.unfold unf a
453 ls <- S.toList $ S.unfold unf a
454 return $ ls == [a..b]
454 return $ ls == [a..b]
455
455
@@ -457,7 +457,7 @@ unfold0 :: Property
457unfold0 = monadicIO $ do
457unfold0 = monadicIO $ do
458 a <- pick $ choose (0, max_length `div` 2)
458 a <- pick $ choose (0, max_length `div` 2)
459 b <- pick $ choose (0, max_length)
459 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)
461 ls <- S.toList $ IS.unfold0 unf
461 ls <- S.toList $ IS.unfold0 unf
462 return $ ls == [a..b]
462 return $ ls == [a..b]
463
463