diff --git a/benchmark/Streamly/Benchmark/Data/Array/Common.hs b/benchmark/Streamly/Benchmark/Data/Array/Common.hs index 0c58f75f3c..6d7e6b87e0 100644 --- a/benchmark/Streamly/Benchmark/Data/Array/Common.hs +++ b/benchmark/Streamly/Benchmark/Data/Array/Common.hs @@ -71,7 +71,7 @@ onArray -> m (Stream Int) onArray value f arr = S.fold (A.createOf value) $ f $ S.unfold A.reader arr -scanl' value n = composeN n $ onArray value $ S.scanl (Scanl.mkScanl (+) 0) +scanl' value n = composeN n $ onArray value $ S.scanl (Scanl.scanl' (+) 0) scanl1' value n = composeN n $ onArray value $ Stream.scanl1' (+) map value n = composeN n $ onArray value $ fmap (+1) -- map n = composeN n $ A.map (+1) diff --git a/benchmark/Streamly/Benchmark/Data/MutArray.hs b/benchmark/Streamly/Benchmark/Data/MutArray.hs index fa1aef1e5f..eeac64807f 100644 --- a/benchmark/Streamly/Benchmark/Data/MutArray.hs +++ b/benchmark/Streamly/Benchmark/Data/MutArray.hs @@ -155,7 +155,7 @@ composeN n f x = {-# INLINE scanl' #-} scanl' :: MonadIO m => Int -> Int -> Stream Int -> m (Stream Int) -scanl' value n = composeN n $ onArray value $ Stream.scanl (Scanl.mkScanl (+) 0) +scanl' value n = composeN n $ onArray value $ Stream.scanl (Scanl.scanl' (+) 0) {-# INLINE scanl1' #-} scanl1' :: MonadIO m => Int -> Int -> Stream Int -> m (Stream Int) diff --git a/benchmark/Streamly/Benchmark/Data/Stream/Common.hs b/benchmark/Streamly/Benchmark/Data/Stream/Common.hs index d441e303a2..e8b2bf2fc4 100644 --- a/benchmark/Streamly/Benchmark/Data/Stream/Common.hs +++ b/benchmark/Streamly/Benchmark/Data/Stream/Common.hs @@ -84,7 +84,7 @@ import Streamly.Internal.Data.Stream (Stream) import qualified Streamly.Internal.Data.Fold as Fold import qualified Streamly.Internal.Data.Pipe as Pipe import qualified Streamly.Internal.Data.Scanl as Scanl -import qualified Streamly.Internal.Data.Scanr as Scanr +import qualified Streamly.Internal.Data.Scan as Scan import qualified Streamly.Internal.Data.Stream as Stream import Test.Tasty.Bench @@ -433,7 +433,7 @@ foldl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> m b foldl' f z = Stream.fold (Fold.foldl' f z) scanl' :: Monad m => (b -> a -> b) -> b -> Stream m a -> Stream m b -scanl' f z = Stream.scanl (Scanl.mkScanl f z) +scanl' f z = Stream.scanl (Scanl.scanl' f z) {-# INLINE transformMapM #-} transformMapM :: @@ -449,7 +449,7 @@ scanMapM :: => Int -> Stream m Int -> m () -scanMapM n = composeN n $ Stream.scanr (Scanr.functionM return) +scanMapM n = composeN n $ Stream.scanr (Scan.functionM return) {-# INLINE transformComposeMapM #-} transformComposeMapM :: @@ -472,8 +472,8 @@ scanComposeMapM :: scanComposeMapM n = composeN n $ Stream.scanr - (Scanr.functionM (\x -> return (x + 1)) `Scanr.compose` - Scanr.functionM (\x -> return (x + 2))) + (Scan.functionM (\x -> return (x + 1)) `Scan.compose` + Scan.functionM (\x -> return (x + 2))) {-# INLINE transformTeeMapM #-} transformTeeMapM :: @@ -496,8 +496,8 @@ scanTeeMapM :: scanTeeMapM n = composeN n $ Stream.scanr - (Scanr.teeWith (+) (Scanr.functionM (\x -> return (x + 1))) - (Scanr.functionM (\x -> return (x + 2)))) + (Scan.teeWith (+) (Scan.functionM (\x -> return (x + 1))) + (Scan.functionM (\x -> return (x + 2)))) {- {-# INLINE transformZipMapM #-} diff --git a/benchmark/Streamly/Benchmark/Data/Stream/Transform.hs b/benchmark/Streamly/Benchmark/Data/Stream/Transform.hs index 03cb2a8230..89d956bfeb 100644 --- a/benchmark/Streamly/Benchmark/Data/Stream/Transform.hs +++ b/benchmark/Streamly/Benchmark/Data/Stream/Transform.hs @@ -164,7 +164,7 @@ o_1_space_mappingX4 value = sieveScan :: Monad m => Stream m Int -> Stream m Int sieveScan = Stream.mapMaybe snd - . Stream.scanl (Scanl.mkScanlM (\(primes, _) n -> do + . Stream.scanl (Scanl.scanlM' (\(primes, _) n -> do return $ let ps = takeWhile (\p -> p * p <= n) primes in if all (\p -> n `mod` p /= 0) ps diff --git a/core/src/Streamly/Data/Scanr.hs b/core/src/Streamly/Data/Scan.hs similarity index 80% rename from core/src/Streamly/Data/Scanr.hs rename to core/src/Streamly/Data/Scan.hs index 246f26c925..294ba90263 100644 --- a/core/src/Streamly/Data/Scanr.hs +++ b/core/src/Streamly/Data/Scan.hs @@ -1,12 +1,12 @@ -- | --- Module : Streamly.Data.Scanr +-- Module : Streamly.Data.Scan -- Copyright : (c) 2019 Composewell Technologies -- License : BSD3 -- Maintainer : streamly@composewell.com -- Stability : experimental -- Portability : GHC -- --- 'Scanr' is a right scan. The 'Scanr' type facilitates a stateful +-- 'Scan' is a right scan. The 'Scan' type facilitates a stateful -- transformation from a stream to another stream. In addition to simple -- transformation of a stream, scans can also be used to split a stream into -- multiple branches, perform different stateful transformations in each branch @@ -21,14 +21,14 @@ -- stream. -- -- >>> import qualified Streamly.Internal.Data.Fold as Fold --- >>> import qualified Streamly.Internal.Data.Scanr as Scanr +-- >>> import qualified Streamly.Internal.Data.Scan as Scan -- >>> import qualified Streamly.Internal.Data.Stream as Stream -- >>> import Data.Function ((&)) -- --- >>> scan1 = Scanr.function (\x -> x * x) --- >>> scan2 = Scanr.function (\x -> 3 * x) --- >>> scan3 = Scanr.teeWith (+) scan1 scan2 -- Compute x^2 + 3x --- >>> scan4 = Scanr.compose scan1 scan3 -- compute x^2 then pass it to scan3 +-- >>> scan1 = Scan.function (\x -> x * x) +-- >>> scan2 = Scan.function (\x -> 3 * x) +-- >>> scan3 = Scan.teeWith (+) scan1 scan2 -- Compute x^2 + 3x +-- >>> scan4 = Scan.compose scan1 scan3 -- compute x^2 then pass it to scan3 -- -- >>> :{ -- main = @@ -53,10 +53,10 @@ -- one input it can produce at most one output, in other words it can shrink or -- filter a stream but it cannot expand it. -- --- == Scanr vs Scanl +-- == Scan vs Scanl -- --- 'Scanr' is a right scan, and 'Scanl' is a left scan. 'Scanr' is to 'Stream' --- as 'Scanl' is to 'Fold'. 'Scanr' is for composing producer stream +-- 'Scan' is a right scan, and 'Scanl' is a left scan. 'Scan' is to 'Stream' +-- as 'Scanl' is to 'Fold'. 'Scan' is for composing producer stream -- transformations whereas 'Scanl' is for composing consumer stream -- transformations. -- @@ -72,10 +72,10 @@ -- @distribute@: Each input is supplied to all scans and the outputs are zipped -- or merged. -- -module Streamly.Data.Scanr +module Streamly.Data.Scan ( -- * Type - Scanr + Scan -- * Primitive Scans , identity @@ -91,5 +91,5 @@ module Streamly.Data.Scanr ) where -import Streamly.Internal.Data.Scanr +import Streamly.Internal.Data.Scan import Prelude hiding (filter) diff --git a/core/src/Streamly/Data/Scanl.hs b/core/src/Streamly/Data/Scanl.hs index d050e1ddec..5643d1774b 100644 --- a/core/src/Streamly/Data/Scanl.hs +++ b/core/src/Streamly/Data/Scanl.hs @@ -21,10 +21,10 @@ module Streamly.Data.Scanl Scanl -- (..) -- * Constructors - , mkScanl - , mkScanlM - , mkScanl1 - , mkScanl1M + , scanl' + , scanlM' + , scanl1' + , scanl1M' , mkScanr -- * Scans @@ -141,7 +141,7 @@ module Streamly.Data.Scanl -- | Transformations that combine two or more scans. -- ** Scanning - , scanl + , compose , postscanl , postscanlMaybe @@ -173,6 +173,13 @@ module Streamly.Data.Scanl -- ** Key-value Scanners , demux , demuxIO + + -- * Deprecated + , scanl + , mkScanl + , mkScanlM + , mkScanl1 + , mkScanl1M ) where diff --git a/core/src/Streamly/Data/Stream.hs b/core/src/Streamly/Data/Stream.hs index 0b74589df5..87001641f2 100644 --- a/core/src/Streamly/Data/Stream.hs +++ b/core/src/Streamly/Data/Stream.hs @@ -414,12 +414,12 @@ module Streamly.Data.Stream -- ** Scanning By 'Scanl' -- | Useful idioms: -- - -- >>> scanl' f z = Stream.scanl (Scanl.mkScanl f z) - -- >>> scanlM' f z = Stream.scanl (Scanl.mkScanlM f z) - -- >>> postscanl' f z = Stream.postscanl (Scanl.mkScanl f z) - -- >>> postscanlM' f z = Stream.postscanl (Scanl.mkScanlM f z) - -- >>> scanl1' f = Stream.catMaybes . Stream.scanl (Scanl.mkScanl1 f) - -- >>> scanl1M' f = Stream.catMaybes . Stream.scanl (Scanl.mkScanl1M f) + -- >>> scanl' f z = Stream.scanl (Scanl.scanl' f z) + -- >>> scanlM' f z = Stream.scanl (Scanl.scanlM' f z) + -- >>> postscanl' f z = Stream.postscanl (Scanl.scanl' f z) + -- >>> postscanlM' f z = Stream.postscanl (Scanl.scanlM' f z) + -- >>> scanl1' f = Stream.catMaybes . Stream.scanl (Scanl.scanl1' f) + -- >>> scanl1M' f = Stream.catMaybes . Stream.scanl (Scanl.scanl1M' f) , scanl , postscanl -- XXX postscan1 can be implemented using Monoids or Refolds. diff --git a/core/src/Streamly/Internal/Data/Fold/Type.hs b/core/src/Streamly/Internal/Data/Fold/Type.hs index 071676c3f0..6912020723 100644 --- a/core/src/Streamly/Internal/Data/Fold/Type.hs +++ b/core/src/Streamly/Internal/Data/Fold/Type.hs @@ -625,7 +625,7 @@ fromScanl (Scanl step initial extract final) = Fold step initial extract final -- {-# INLINE foldl' #-} foldl' :: Monad m => (b -> a -> b) -> b -> Fold m a b -foldl' step = fromScanl . Scanl.mkScanl step +foldl' step = fromScanl . Scanl.scanl' step -- | Make a fold from a left fold style monadic step function and initial value -- of the accumulator. @@ -639,7 +639,7 @@ foldl' step = fromScanl . Scanl.mkScanl step -- {-# INLINE foldlM' #-} foldlM' :: Monad m => (b -> a -> m b) -> m b -> Fold m a b -foldlM' step = fromScanl . Scanl.mkScanlM step +foldlM' step = fromScanl . Scanl.scanlM' step -- | Make a strict left fold, for non-empty streams, using first element as the -- starting value. Returns Nothing if the stream is empty. @@ -647,7 +647,7 @@ foldlM' step = fromScanl . Scanl.mkScanlM step -- /Pre-release/ {-# INLINE foldl1' #-} foldl1' :: Monad m => (a -> a -> a) -> Fold m a (Maybe a) -foldl1' = fromScanl . Scanl.mkScanl1 +foldl1' = fromScanl . Scanl.scanl1' -- | Like 'foldl1\'' but with a monadic step function. -- @@ -662,7 +662,7 @@ foldlM1' = foldl1M' -- /Pre-release/ {-# INLINE foldl1M' #-} foldl1M' :: Monad m => (a -> a -> m a) -> Fold m a (Maybe a) -foldl1M' = fromScanl . Scanl.mkScanl1M +foldl1M' = fromScanl . Scanl.scanl1M' {- data FromScan s b = FromScanInit !s | FromScanGo !s !b @@ -775,7 +775,7 @@ foldrM' g = fromScanl . Scanl.mkScanrM g -- {-# INLINE foldt' #-} foldt' :: Monad m => (s -> a -> Step s b) -> Step s b -> (s -> b) -> Fold m a b -foldt' step initial = fromScanl . Scanl.mkScant step initial +foldt' step initial = fromScanl . Scanl.scant' step initial -- | Make a terminating fold with an effectful step function and initial state, -- and a state extraction function. diff --git a/core/src/Streamly/Internal/Data/Pipe/Type.hs b/core/src/Streamly/Internal/Data/Pipe/Type.hs index 1624168279..b6acb44d59 100644 --- a/core/src/Streamly/Internal/Data/Pipe/Type.hs +++ b/core/src/Streamly/Internal/Data/Pipe/Type.hs @@ -14,7 +14,7 @@ module Streamly.Internal.Data.Pipe.Type -- * From folds , fromStream - , fromScanr + , fromScan , fromFold , scanFold @@ -41,7 +41,7 @@ import Data.Kind (Type) #endif import Fusion.Plugin.Types (Fuse(..)) import Streamly.Internal.Data.Fold.Type (Fold(..)) -import Streamly.Internal.Data.Scanr (Scanr(..)) +import Streamly.Internal.Data.Scan (Scan(..)) import Streamly.Internal.Data.Stream.Type (Stream(..)) -- import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..)) import Streamly.Internal.Data.SVar.Type (defState) @@ -714,9 +714,9 @@ fromStream (Stream step state) = Pipe consume produce () Stream.Skip s -> SkipP s Stream.Stop -> Stop -{-# INLINE fromScanr #-} -fromScanr :: Monad m => Scanr m a b -> Pipe m a b -fromScanr (Scanr step initial) = Pipe consume undefined initial +{-# INLINE fromScan #-} +fromScan :: Monad m => Scan m a b -> Pipe m a b +fromScan (Scan step initial) = Pipe consume undefined initial where diff --git a/core/src/Streamly/Internal/Data/Scanr.hs b/core/src/Streamly/Internal/Data/Scan.hs similarity index 65% rename from core/src/Streamly/Internal/Data/Scanr.hs rename to core/src/Streamly/Internal/Data/Scan.hs index 995cfcd301..ae08a1a7d0 100644 --- a/core/src/Streamly/Internal/Data/Scanr.hs +++ b/core/src/Streamly/Internal/Data/Scan.hs @@ -1,5 +1,5 @@ -- | --- Module : Streamly.Internal.Data.Scanr +-- Module : Streamly.Internal.Data.Scan -- Copyright : (c) 2019 Composewell Technologies -- License : BSD3 -- Maintainer : streamly@composewell.com @@ -8,13 +8,13 @@ -- -- Right scans. -- --- == Scanr vs Stream +-- == Scan vs Stream -- -- A scan is a generalization of a stream. Like streams, a scan has an internal -- state. Unlike a stream, a scan produces an output only on an input, the -- output is a function of the scan state and the input. A scan produces at -- most one output on one input, in other words it is driven solely by the --- input, it cannot produce output on its own. A @Scanr m () a@ can represent a +-- input, it cannot produce output on its own. A @Scan m () a@ can represent a -- @Stream m a@ by supplying the scan with () inputs. -- -- == Scans vs pipes: @@ -42,10 +42,16 @@ -- Another option could be if a Scan terminates do we want to start it again or -- not. -module Streamly.Internal.Data.Scanr +module Streamly.Internal.Data.Scan ( -- * Type - Scanr (..) + Scan (..) + + -- * Constructors + , postscanl' + , postscanlM' + , mapAccum + , mapAccumM -- * Primitive Scans , identity @@ -85,7 +91,7 @@ import Prelude hiding -- >>> import Control.Category -- -- >>> import qualified Streamly.Internal.Data.Fold as Fold --- >>> import qualified Streamly.Internal.Data.Scanr as Scanr +-- >>> import qualified Streamly.Internal.Data.Scan as Scan -- >>> import qualified Streamly.Internal.Data.Stream as Stream ------------------------------------------------------------------------------ @@ -112,8 +118,8 @@ import Prelude hiding -- type @a@ to outputs of type @b@ in 'Monad' @m@. -- -- The constructor is @Scan consume initial@. -data Scanr m a b = - forall s. Scanr +data Scan m a b = + forall s. Scan (s -> a -> m (Step s b)) s @@ -123,18 +129,101 @@ data Scanr m a b = -- | 'fmap' maps a pure function on a scan output. -- --- >>> Stream.toList $ Stream.scanr (fmap (+1) Scanr.identity) $ Stream.fromList [1..5::Int] +-- >>> Stream.toList $ Stream.scanr (fmap (+1) Scan.identity) $ Stream.fromList [1..5::Int] -- [2,3,4,5,6] -- -instance Functor m => Functor (Scanr m a) where +instance Functor m => Functor (Scan m a) where {-# INLINE_NORMAL fmap #-} - fmap f (Scanr consume initial) = Scanr consume1 initial + fmap f (Scan consume initial) = Scan consume1 initial where {-# INLINE_LATE consume1 #-} consume1 s b = fmap (fmap f) (consume s b) +------------------------------------------------------------------------------- +-- Constructors +------------------------------------------------------------------------------- + +{- +-- Nested fmaps are commonly needed. Should put them in a resuable module. +{-# INLINE fmap2 #-} +fmap2 :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b) +fmap2 = fmap Prelude.. fmap +-} + +-- NOTE: this may not be very useful as a general function. Users may not want +-- to fmap a function over the result of a function, they can just call that +-- other function on the retult. liftResult2 is a special case to avoid that +-- call in this special case because it is common. + +-- | Map a function over the result of a binary function. +-- +-- >> mapResult2 f g x = f . g x +-- >> mapResult2 f = fmap2 f +-- +{-# INLINE mapResult2 #-} +mapResult2 :: (c -> d) -> (a -> b -> c) -> (a -> b -> d) +mapResult2 f g x = f Prelude.. g x + +-- | Lift the result of a binary function to an Applicative. +{-# INLINE liftResult2 #-} +liftResult2 :: Applicative m => (a -> b -> c) -> (a -> b -> m c) +liftResult2 = mapResult2 pure + +-- | Like 'postscanl'' but with a monadic step function. +-- +{-# INLINE postscanlM' #-} +postscanlM' :: Monad m => (b -> a -> m b) -> b -> Scan m a b +postscanlM' step = Scan consume + + where + + {-# INLINE_LATE consume #-} + consume s a = do + !s1 <- step s a + return (Yield s1 s1) + +-- | Make a scan from a left fold style pure step function and an initial value +-- of the accumulator. The accumulator is also the output of the scan (Moore +-- style). +-- +-- >>> Stream.toList $ Stream.scanr (Scan.postscanl' (+) 0) $ Stream.fromList [1..5::Int] +-- [1,3,6,10,15] +-- +{-# INLINE postscanl' #-} +postscanl' :: Monad m => (b -> a -> b) -> b -> Scan m a b +postscanl' reducer = postscanlM' (liftResult2 reducer) + +-- XXX if we change Yield b s to Yield s b, it will be equivalent to the tuple +-- returned by the mapAccum, it is essentially Partial s b of fold Step. We +-- should probably make a single convention across Stream, Scan, Fold, Parser. +-- Even the subtypes like the tuple (s,b) in mapAccum should follow the same +-- convention. + +-- | Like 'mapAccum' but with a monadic step function. +-- +{-# INLINE mapAccumM #-} +mapAccumM :: Monad m => (s -> a -> m (s, b)) -> s -> Scan m a b +mapAccumM step = Scan consume + + where + + {-# INLINE_LATE consume #-} + consume s a = do + (!s1, b) <- step s a + return (Yield b s1) + +-- | Make a scan from a Mealy style pure step function and an initial state. +-- The step function returns the next state and the output separately. +-- +-- >>> Stream.toList $ Stream.scanr (Scan.mapAccum (\s a -> (s + a, s)) 0) $ Stream.fromList [1..5::Int] +-- [0,1,3,6,10] +-- +{-# INLINE mapAccum #-} +mapAccum :: Monad m => (s -> a -> (s, b)) -> s -> Scan m a b +mapAccum reducer = mapAccumM (liftResult2 reducer) + ------------------------------------------------------------------------------- -- Category ------------------------------------------------------------------------------- @@ -146,14 +235,14 @@ instance Functor m => Functor (Scanr m a) where -- second scan. -- -- >>> import Control.Category --- >>> Stream.toList $ Stream.scanr (Scanr.function (+1) >>> Scanr.function (+1)) $ Stream.fromList [1..5::Int] +-- >>> Stream.toList $ Stream.scanr (Scan.function (+1) >>> Scan.function (+1)) $ Stream.fromList [1..5::Int] -- [3,4,5,6,7] -- {-# INLINE_NORMAL compose #-} -compose :: Monad m => Scanr m b c -> Scanr m a b -> Scanr m a c +compose :: Monad m => Scan m b c -> Scan m a b -> Scan m a c compose - (Scanr stepR initialR) - (Scanr stepL initialL) = Scanr step (initialL, initialR) + (Scan stepR initialR) + (Scan stepL initialL) = Scan step (initialL, initialR) where @@ -173,7 +262,7 @@ compose -- | A scan representing mapping of a monadic action. -- --- >>> Stream.toList $ Stream.scanr (Scanr.functionM print) $ Stream.fromList [1..5::Int] +-- >>> Stream.toList $ Stream.scanr (Scan.functionM print) $ Stream.fromList [1..5::Int] -- 1 -- 2 -- 3 @@ -182,32 +271,32 @@ compose -- [(),(),(),(),()] -- {-# INLINE functionM #-} -functionM :: Monad m => (a -> m b) -> Scanr m a b -functionM f = Scanr (\() a -> fmap (`Yield` ()) (f a)) () +functionM :: Monad m => (a -> m b) -> Scan m a b +functionM f = Scan (\() a -> fmap (`Yield` ()) (f a)) () -- | A scan representing mapping of a pure function. -- --- >>> Stream.toList $ Stream.scanr (Scanr.function (+1)) $ Stream.fromList [1..5::Int] +-- >>> Stream.toList $ Stream.scanr (Scan.function (+1)) $ Stream.fromList [1..5::Int] -- [2,3,4,5,6] -- {-# INLINE function #-} -function :: Monad m => (a -> b) -> Scanr m a b +function :: Monad m => (a -> b) -> Scan m a b function f = functionM (return Prelude.. f) {- HLINT ignore "Redundant map" -} -- | An identity scan producing the same output as input. -- --- >>> identity = Scanr.function Prelude.id +-- >>> identity = Scan.function Prelude.id -- --- >>> Stream.toList $ Stream.scanr (Scanr.identity) $ Stream.fromList [1..5::Int] +-- >>> Stream.toList $ Stream.scanr (Scan.identity) $ Stream.fromList [1..5::Int] -- [1,2,3,4,5] -- {-# INLINE identity #-} -identity :: Monad m => Scanr m a a +identity :: Monad m => Scan m a a identity = function Prelude.id -instance Monad m => Category (Scanr m) where +instance Monad m => Category (Scan m) where {-# INLINE id #-} id = identity @@ -227,14 +316,14 @@ data TeeWith sL sR = TeeWith !sL !sR -- zip their outputs. If the scan filters the output, 'Nothing' is emitted -- otherwise 'Just' is emitted. The scan stops if any of the scans stop. -- --- >>> Stream.toList $ Stream.scanr (Scanr.teeWithMay (,) Scanr.identity (Scanr.function (\x -> x * x))) $ Stream.fromList [1..5::Int] +-- >>> Stream.toList $ Stream.scanr (Scan.teeWithMay (,) Scan.identity (Scan.function (\x -> x * x))) $ Stream.fromList [1..5::Int] -- [(Just 1,Just 1),(Just 2,Just 4),(Just 3,Just 9),(Just 4,Just 16),(Just 5,Just 25)] -- {-# INLINE_NORMAL teeWithMay #-} teeWithMay :: Monad m => - (Maybe b -> Maybe c -> d) -> Scanr m a b -> Scanr m a c -> Scanr m a d -teeWithMay f (Scanr stepL initialL) (Scanr stepR initialR) = - Scanr step (TeeWith initialL initialR) + (Maybe b -> Maybe c -> d) -> Scan m a b -> Scan m a c -> Scan m a d +teeWithMay f (Scan stepL initialL) (Scan stepR initialR) = + Scan step (TeeWith initialL initialR) where @@ -271,26 +360,26 @@ teeWithMay f (Scanr stepL initialL) (Scanr stepR initialR) = -- the scans skips the output then the composed scan also skips. Stops when any -- of the scans stop. -- --- >>> Stream.toList $ Stream.scanr (Scanr.teeWith (,) Scanr.identity (Scanr.function (\x -> x * x))) $ Stream.fromList [1..5::Int] +-- >>> Stream.toList $ Stream.scanr (Scan.teeWith (,) Scan.identity (Scan.function (\x -> x * x))) $ Stream.fromList [1..5::Int] -- [(1,1),(2,4),(3,9),(4,16),(5,25)] -- {-# INLINE_NORMAL teeWith #-} teeWith :: Monad m => - (b -> c -> d) -> Scanr m a b -> Scanr m a c -> Scanr m a d + (b -> c -> d) -> Scan m a b -> Scan m a c -> Scan m a d teeWith f s1 s2 = fmap fromJust $ compose (filter isJust) $ teeWithMay (\b c -> f <$> b <*> c) s1 s2 -- | Zips the outputs only when both scans produce outputs, discards otherwise. -instance Monad m => Applicative (Scanr m a) where +instance Monad m => Applicative (Scan m a) where {-# INLINE pure #-} - pure b = Scanr (\_ _ -> pure $ Yield b ()) () + pure b = Scan (\_ _ -> pure $ Yield b ()) () (<*>) = teeWith id {-# INLINE_NORMAL tee #-} -tee :: Monad m => Scanr m a b -> Scanr m a c -> Scanr m a (b,c) +tee :: Monad m => Scan m a b -> Scan m a c -> Scan m a (b,c) tee = teeWith (,) ------------------------------------------------------------------------------- @@ -304,9 +393,9 @@ tee = teeWith (,) -- {-# INLINE_NORMAL unzipMay #-} unzipMay :: Monad m => - Scanr m a x -> Scanr m b y -> Scanr m (a, b) (Maybe x, Maybe y) -unzipMay (Scanr stepL initialL) (Scanr stepR initialR) = - Scanr step (Tuple' initialL initialR) + Scan m a x -> Scan m b y -> Scan m (a, b) (Maybe x, Maybe y) +unzipMay (Scan stepL initialL) (Scan stepR initialR) = + Scan step (Tuple' initialL initialR) where @@ -342,7 +431,7 @@ unzipMay (Scanr stepL initialL) (Scanr stepR initialR) = -- | Like 'unzipMay' but produces an output only when both the scans produce an -- output. Other outputs are filtered out. {-# INLINE_NORMAL unzip #-} -unzip :: Monad m => Scanr m a x -> Scanr m b y -> Scanr m (a, b) (x, y) +unzip :: Monad m => Scan m a x -> Scan m b y -> Scan m (a, b) (x, y) unzip s1 s2 = fmap (fromJust Prelude.. f) $ unzipMay s1 s2 where @@ -355,7 +444,7 @@ unzip s1 s2 = fmap (fromJust Prelude.. f) $ unzipMay s1 s2 Nothing -> Nothing Nothing -> Nothing -instance Monad m => Arrow (Scanr m) where +instance Monad m => Arrow (Scan m) where {-# INLINE arr #-} arr = function @@ -371,8 +460,8 @@ instance Monad m => Arrow (Scanr m) where -- | A filtering scan using a monadic predicate. {-# INLINE filterM #-} -filterM :: Monad m => (a -> m Bool) -> Scanr m a a -filterM f = Scanr (\() a -> f a >>= g a) () +filterM :: Monad m => (a -> m Bool) -> Scan m a a +filterM f = Scan (\() a -> f a >>= g a) () where @@ -385,17 +474,17 @@ filterM f = Scanr (\() a -> f a >>= g a) () -- | A filtering scan using a pure predicate. -- --- >>> Stream.toList $ Stream.scanr (Scanr.filter odd) $ Stream.fromList [1..5::Int] +-- >>> Stream.toList $ Stream.scanr (Scan.filter odd) $ Stream.fromList [1..5::Int] -- [1,3,5] -- {-# INLINE filter #-} -filter :: Monad m => (a -> Bool) -> Scanr m a a +filter :: Monad m => (a -> Bool) -> Scan m a a filter f = filterM (return Prelude.. f) {-# INLINE length #-} -length :: Monad m => Scanr m a Int -length = Scanr (\acc _ -> pure $ let !n = acc + 1 in Yield n n) 0 +length :: Monad m => Scan m a Int +length = Scan (\acc _ -> pure $ let !n = acc + 1 in Yield n n) 0 {-# INLINE sum #-} -sum :: (Monad m, Num a) => Scanr m a a -sum = Scanr (\acc x -> pure $ let !n = acc + x in Yield n n) 0 +sum :: (Monad m, Num a) => Scan m a a +sum = Scan (\acc x -> pure $ let !n = acc + x in Yield n n) 0 diff --git a/core/src/Streamly/Internal/Data/Scanl/Combinators.hs b/core/src/Streamly/Internal/Data/Scanl/Combinators.hs index 64f3ec91c5..a9739e366d 100644 --- a/core/src/Streamly/Internal/Data/Scanl/Combinators.hs +++ b/core/src/Streamly/Internal/Data/Scanl/Combinators.hs @@ -126,8 +126,8 @@ module Streamly.Internal.Data.Scanl.Combinators -- , slide2 -- ** Scanning Input - , scanl - , scanlMany + , compose + , composeMany -- , runScan , pipe , indexed @@ -197,11 +197,16 @@ module Streamly.Internal.Data.Scanl.Combinators -- ** Nesting , unfoldMany -- , concatSequence + + -- * Deprecated + , scanl + , scanlMany ) where #include "inline.hs" #include "ArrayMacros.h" +#include "deprecation.h" -- import Control.Monad (void) import Control.Monad.IO.Class (MonadIO(..)) @@ -527,9 +532,9 @@ scanWith isMany -- This is basically an append operation. -- -- /Pre-release/ -{-# INLINE scanl #-} -scanl :: Monad m => Scanl m a b -> Scanl m b c -> Scanl m a c -scanl = scanWith False +{-# INLINE compose #-} +compose, scanl :: Monad m => Scanl m a b -> Scanl m b c -> Scanl m a c +compose = scanWith False -- XXX This does not fuse beacuse of the recursive step. Need to investigate. @@ -537,9 +542,9 @@ scanl = scanWith False -- another 'Scanl'. The scan restarts with a fresh state if it terminates. -- -- /Pre-release/ -{-# INLINE scanlMany #-} -scanlMany :: Monad m => Scanl m a b -> Scanl m b c -> Scanl m a c -scanlMany = scanWith True +{-# INLINE composeMany #-} +composeMany, scanlMany :: Monad m => Scanl m a b -> Scanl m b c -> Scanl m a c +composeMany = scanWith True ------------------------------------------------------------------------------ -- Filters @@ -556,7 +561,7 @@ scanlMany = scanWith True -- {-# INLINE_NORMAL deleteBy #-} deleteBy :: Monad m => (a -> a -> Bool) -> a -> Scanl m a (Maybe a) -deleteBy eq x0 = fmap extract $ mkScanl step (Tuple' False Nothing) +deleteBy eq x0 = fmap extract $ scanl' step (Tuple' False Nothing) where @@ -713,7 +718,7 @@ drainMapM f = lmapM f drain -- {-# INLINE the #-} the :: (Monad m, Eq a) => Scanl m a (Maybe a) -the = mkScant step initial id +the = scant' step initial id where @@ -737,7 +742,7 @@ the = mkScant step initial id -- -- Same as following but numerically stable: -- --- >>> sum = Scanl.mkScanl (+) 0 +-- >>> sum = Scanl.scanl' (+) 0 -- >>> sum = fmap Data.Monoid.getSum $ Scanl.foldMap Data.Monoid.Sum -- {-# INLINE sum #-} @@ -754,7 +759,7 @@ sum = Scanl.cumulativeScan Scanl.incrSum -- {-# INLINE product #-} product :: (Monad m, Num a, Eq a) => Scanl m a a -product = mkScant step (Partial 1) id +product = scant' step (Partial 1) id where @@ -772,7 +777,7 @@ product = mkScant step (Partial 1) id -- {-# INLINE mean #-} mean :: (Monad m, Fractional a) => Scanl m a a -mean = fmap done $ mkScanl step begin +mean = fmap done $ scanl' step begin where @@ -797,7 +802,7 @@ mean = fmap done $ mkScanl step begin -- {-# INLINE rollingHashWithSalt #-} rollingHashWithSalt :: (Monad m, Enum a) => Int64 -> Scanl m a Int64 -rollingHashWithSalt = mkScanl step +rollingHashWithSalt = scanl' step where @@ -837,7 +842,7 @@ rollingHashFirstN n = take n rollingHash -- -- Definition: -- --- >>> sconcat = Scanl.mkScanl (<>) +-- >>> sconcat = Scanl.scanl' (<>) -- -- >>> semigroups = fmap Data.Monoid.Sum $ Stream.enumerateFromTo 1 3 -- >>> Stream.toList $ Stream.scanl (Scanl.sconcat 3) semigroups @@ -845,7 +850,7 @@ rollingHashFirstN n = take n rollingHash -- {-# INLINE sconcat #-} sconcat :: (Monad m, Semigroup a) => a -> Scanl m a a -sconcat = mkScanl (<>) +sconcat = scanl' (<>) -- | Monoid concat. Scan an input stream consisting of monoidal elements using -- 'mappend' and 'mempty'. @@ -894,7 +899,7 @@ foldMap f = lmap f mconcat -- {-# INLINE foldMapM #-} foldMapM :: (Monad m, Monoid b) => (a -> m b) -> Scanl m a b -foldMapM act = mkScanlM step (pure mempty) +foldMapM act = scanlM' step (pure mempty) where @@ -914,7 +919,7 @@ foldMapM act = mkScanlM step (pure mempty) -- -- Definition: -- --- >>> toListRev = Scanl.mkScanl (flip (:)) [] +-- >>> toListRev = Scanl.scanl' (flip (:)) [] -- -- /Warning!/ working on large lists accumulated as buffers in memory could be -- very inefficient, consider using "Streamly.Array" instead. @@ -923,7 +928,7 @@ foldMapM act = mkScanlM step (pure mempty) -- xn : ... : x2 : x1 : [] {-# INLINE toListRev #-} toListRev :: Monad m => Scanl m a [a] -toListRev = mkScanl (flip (:)) [] +toListRev = scanl' (flip (:)) [] ------------------------------------------------------------------------------ -- Partial Scans @@ -951,7 +956,7 @@ drainN n = take n drain -- /Pre-release/ {-# INLINE genericIndex #-} genericIndex :: (Integral i, Monad m) => i -> Scanl m a (Maybe a) -genericIndex i = mkScant step (Partial 0) (const Nothing) +genericIndex i = scant' step (Partial 0) (const Nothing) where @@ -977,7 +982,7 @@ index = genericIndex -- {-# INLINE maybe #-} maybe :: Monad m => (a -> Maybe b) -> Scanl m a (Maybe b) -maybe f = mkScant (const (Done . f)) (Partial Nothing) id +maybe f = scant' (const (Done . f)) (Partial Nothing) id -- | Consume a single element and return it if it passes the predicate else -- return 'Nothing'. @@ -1069,7 +1074,7 @@ find p = findM (return . p) -- {-# INLINE lookup #-} lookup :: (Eq a, Monad m) => a -> Scanl m (a,b) (Maybe b) -lookup a0 = mkScant step (Partial ()) (const Nothing) +lookup a0 = scant' step (Partial ()) (const Nothing) where @@ -1082,7 +1087,7 @@ lookup a0 = mkScant step (Partial ()) (const Nothing) -- {-# INLINE findIndex #-} findIndex :: Monad m => (a -> Bool) -> Scanl m a (Maybe Int) -findIndex predicate = mkScant step (Partial 0) (const Nothing) +findIndex predicate = scant' step (Partial 0) (const Nothing) where @@ -1099,7 +1104,7 @@ findIndex predicate = mkScant step (Partial 0) (const Nothing) findIndices :: Monad m => (a -> Bool) -> Scanl m a (Maybe Int) findIndices predicate = -- XXX implement by combining indexing and filtering scans - fmap (either (Prelude.const Nothing) Just) $ mkScanl step (Left (-1)) + fmap (either (Prelude.const Nothing) Just) $ scanl' step (Left (-1)) where @@ -1149,7 +1154,7 @@ elemIndex a = findIndex (== a) -- {-# INLINE null #-} null :: Monad m => Scanl m a Bool -null = mkScant (\() _ -> Done False) (Partial ()) (const True) +null = scant' (\() _ -> Done False) (Partial ()) (const True) -- | Returns 'True' if any element of the input satisfies the predicate. -- @@ -1164,7 +1169,7 @@ null = mkScant (\() _ -> Done False) (Partial ()) (const True) -- {-# INLINE any #-} any :: Monad m => (a -> Bool) -> Scanl m a Bool -any predicate = mkScant step initial id +any predicate = scant' step initial id where @@ -1198,7 +1203,7 @@ elem a = any (== a) -- {-# INLINE all #-} all :: Monad m => (a -> Bool) -> Scanl m a Bool -all predicate = mkScant step initial id +all predicate = scant' step initial id where @@ -2051,7 +2056,7 @@ zipStream = zipStreamWithM (curry return) -- {-# INLINE indexingWith #-} indexingWith :: Monad m => Int -> (Int -> Int) -> Scanl m a (Maybe (Int, a)) -indexingWith i f = fmap toMaybe $ mkScanl step initial +indexingWith i f = fmap toMaybe $ scanl' step initial where @@ -2391,3 +2396,10 @@ intersperseWithQuotes _ <- finalL sL error "intersperseWithQuotes: finished inside quote, at escape char" -} + +------------------------------------------------------------------------------ +-- Deprecated +------------------------------------------------------------------------------ + +RENAME(scanl,compose) +RENAME(scanlMany,composeMany) diff --git a/core/src/Streamly/Internal/Data/Scanl/Container.hs b/core/src/Streamly/Internal/Data/Scanl/Container.hs index 58e959a0a2..643bd14f34 100644 --- a/core/src/Streamly/Internal/Data/Scanl/Container.hs +++ b/core/src/Streamly/Internal/Data/Scanl/Container.hs @@ -114,22 +114,22 @@ import Streamly.Internal.Data.Scanl.Type -- -- Definition: -- --- >>> toSet = Scanl.mkScanl (flip Set.insert) Set.empty +-- >>> toSet = Scanl.scanl' (flip Set.insert) Set.empty -- {-# INLINE toSet #-} toSet :: (Monad m, Ord a) => Scanl m a (Set a) -toSet = mkScanl (flip Set.insert) Set.empty +toSet = scanl' (flip Set.insert) Set.empty -- | Scan the input adding it to an int set. For integer inputs this performs -- better than 'toSet'. -- -- Definition: -- --- >>> toIntSet = Scanl.mkScanl (flip IntSet.insert) IntSet.empty +-- >>> toIntSet = Scanl.scanl' (flip IntSet.insert) IntSet.empty -- {-# INLINE toIntSet #-} toIntSet :: Monad m => Scanl m Int IntSet -toIntSet = mkScanl (flip IntSet.insert) IntSet.empty +toIntSet = scanl' (flip IntSet.insert) IntSet.empty -- XXX Name as nubOrd? Or write a nubGeneric @@ -145,7 +145,7 @@ toIntSet = mkScanl (flip IntSet.insert) IntSet.empty -- /Pre-release/ {-# INLINE nub #-} nub :: (Monad m, Ord a) => Scanl m a (Maybe a) -nub = fmap (\(Tuple' _ x) -> x) $ mkScanl step initial +nub = fmap (\(Tuple' _ x) -> x) $ scanl' step initial where @@ -161,7 +161,7 @@ nub = fmap (\(Tuple' _ x) -> x) $ mkScanl step initial -- /Pre-release/ {-# INLINE nubInt #-} nubInt :: Monad m => Scanl m Int (Maybe Int) -nubInt = fmap (\(Tuple' _ x) -> x) $ mkScanl step initial +nubInt = fmap (\(Tuple' _ x) -> x) $ scanl' step initial where @@ -484,7 +484,7 @@ demuxIO getKey = fmap snd . demuxUsingMapIO getKey {-# INLINE kvToMapOverwriteGeneric #-} kvToMapOverwriteGeneric :: (Monad m, IsMap f) => Scanl m (Key f, a) (f a) kvToMapOverwriteGeneric = - mkScanl (\kv (k, v) -> IsMap.mapInsert k v kv) IsMap.mapEmpty + scanl' (\kv (k, v) -> IsMap.mapInsert k v kv) IsMap.mapEmpty {-# INLINE demuxToContainer #-} demuxToContainer :: (Monad m, IsMap f, Traversable f) => diff --git a/core/src/Streamly/Internal/Data/Scanl/Type.hs b/core/src/Streamly/Internal/Data/Scanl/Type.hs index 95498733a7..33483a1131 100644 --- a/core/src/Streamly/Internal/Data/Scanl/Type.hs +++ b/core/src/Streamly/Internal/Data/Scanl/Type.hs @@ -78,12 +78,12 @@ module Streamly.Internal.Data.Scanl.Type , Scanl (..) -- * Constructors - , mkScanl - , mkScanlM - , mkScanl1 - , mkScanl1M - , mkScant - , mkScantM + , scanl' + , scanlM' + , scanl1' + , scanl1M' + , scant' + , scantM' , mkScanr , mkScanrM @@ -181,10 +181,19 @@ module Streamly.Internal.Data.Scanl.Type -- * Transforming inner monad , morphInner , generalizeInner + + -- * Deprecated + , mkScanl + , mkScanlM + , mkScanl1 + , mkScanl1M + , mkScant + , mkScantM ) where #include "inline.hs" +#include "deprecation.h" #if !MIN_VERSION_base(4,18,0) import Control.Applicative (liftA2) @@ -319,11 +328,11 @@ rmapM f (Scanl step initial extract final) = -- the accumulator. -- -- If your 'Scanl' returns only 'Partial' (i.e. never returns a 'Done') then --- you can use @mkScanl*@ constructors. +-- you can use @scanl*'@ constructors. -- -{-# INLINE mkScanl #-} -mkScanl :: Monad m => (b -> a -> b) -> b -> Scanl m a b -mkScanl step initial = +{-# INLINE scanl' #-} +scanl', mkScanl :: Monad m => (b -> a -> b) -> b -> Scanl m a b +scanl' step initial = Scanl (\s a -> return $ Partial $ step s a) (return (Partial initial)) @@ -333,9 +342,9 @@ mkScanl step initial = -- | Make a scan from a left fold style monadic step function and initial value -- of the accumulator. -- -{-# INLINE mkScanlM #-} -mkScanlM :: Monad m => (b -> a -> m b) -> m b -> Scanl m a b -mkScanlM step initial = +{-# INLINE scanlM' #-} +scanlM', mkScanlM :: Monad m => (b -> a -> m b) -> m b -> Scanl m a b +scanlM' step initial = Scanl (\s a -> Partial <$> step s a) (Partial <$> initial) return return -- | Maps a function on the output of the scan (the type @b@). @@ -354,21 +363,21 @@ instance Functor m => Functor (Scanl m a) where -- starting value. Returns Nothing if the stream is empty. -- -- /Pre-release/ -{-# INLINE mkScanl1 #-} -mkScanl1 :: Monad m => (a -> a -> a) -> Scanl m a (Maybe a) -mkScanl1 step = fmap toMaybe $ mkScanl step1 Nothing' +{-# INLINE scanl1' #-} +scanl1', mkScanl1 :: Monad m => (a -> a -> a) -> Scanl m a (Maybe a) +scanl1' step = fmap toMaybe $ scanl' step1 Nothing' where step1 Nothing' a = Just' a step1 (Just' x) a = Just' $ step x a --- | Like 'mkScanl1' but with a monadic step function. +-- | Like 'scanl1'' but with a monadic step function. -- -- /Pre-release/ -{-# INLINE mkScanl1M #-} -mkScanl1M :: Monad m => (a -> a -> m a) -> Scanl m a (Maybe a) -mkScanl1M step = fmap toMaybe $ mkScanlM step1 (return Nothing') +{-# INLINE scanl1M' #-} +scanl1M', mkScanl1M :: Monad m => (a -> a -> m a) -> Scanl m a (Maybe a) +scanl1M' step = fmap toMaybe $ scanlM' step1 (return Nothing') where @@ -429,7 +438,7 @@ fromScan (Scan consume initial) = -- Definitions: -- -- >>> mkScanr f z = fmap (flip appEndo z) $ Scanl.foldMap (Endo . f) --- >>> mkScanr f z = fmap ($ z) $ Scanl.mkScanl (\g x -> g . f x) id +-- >>> mkScanr f z = fmap ($ z) $ Scanl.scanl' (\g x -> g . f x) id -- -- Example: -- @@ -438,7 +447,7 @@ fromScan (Scan consume initial) = -- {-# INLINE mkScanr #-} mkScanr :: Monad m => (a -> b -> b) -> b -> Scanl m a b -mkScanr f z = fmap ($ z) $ mkScanl (\g x -> g . f x) id +mkScanr f z = fmap ($ z) $ scanl' (\g x -> g . f x) id -- XXX we have not seen any use of this yet, not releasing until we have a use -- case. @@ -453,7 +462,7 @@ mkScanr f z = fmap ($ z) $ mkScanl (\g x -> g . f x) id {-# INLINE mkScanrM #-} mkScanrM :: Monad m => (a -> b -> m b) -> m b -> Scanl m a b mkScanrM g z = - rmapM (z >>=) $ mkScanlM (\f x -> return $ g x >=> f) (return return) + rmapM (z >>=) $ scanlM' (\f x -> return $ g x >=> f) (return return) ------------------------------------------------------------------------------ -- General scan constructors @@ -478,9 +487,9 @@ mkScanrM g z = -- -- /Pre-release/ -- -{-# INLINE mkScant #-} -mkScant :: Monad m => (s -> a -> Step s b) -> Step s b -> (s -> b) -> Scanl m a b -mkScant step initial extract = +{-# INLINE scant' #-} +scant', mkScant :: Monad m => (s -> a -> Step s b) -> Step s b -> (s -> b) -> Scanl m a b +scant' step initial extract = Scanl (\s a -> return $ step s a) (return initial) @@ -490,15 +499,15 @@ mkScant step initial extract = -- | Make a terminating scan with an effectful step function and initial state, -- and a state extraction function. -- --- >>> mkScantM = Scanl.Scanl +-- >>> scantM' = Scanl.Scanl -- -- We can just use 'Scanl' but it is provided for completeness. -- -- /Pre-release/ -- -{-# INLINE mkScantM #-} -mkScantM :: (s -> a -> m (Step s b)) -> m (Step s b) -> (s -> m b) -> Scanl m a b -mkScantM step initial extract = Scanl step initial extract extract +{-# INLINE scantM' #-} +scantM', mkScantM :: (s -> a -> m (Step s b)) -> m (Step s b) -> (s -> m b) -> Scanl m a b +scantM' step initial extract = Scanl step initial extract extract ------------------------------------------------------------------------------ -- Refold @@ -522,20 +531,20 @@ fromRefold (Refold step inject extract) c = -- results. -- -- >>> drain = Scanl.drainMapM (const (return ())) --- >>> drain = Scanl.mkScanl (\_ _ -> ()) () +-- >>> drain = Scanl.scanl' (\_ _ -> ()) () -- {-# INLINE drain #-} drain :: Monad m => Scanl m a () -drain = mkScanl (\_ _ -> ()) () +drain = scanl' (\_ _ -> ()) () -- | Returns the latest element of the input stream, if any. -- --- >>> latest = Scanl.mkScanl1 (\_ x -> x) +-- >>> latest = Scanl.scanl1' (\_ x -> x) -- >>> latest = fmap getLast $ Scanl.foldMap (Last . Just) -- {-# INLINE latest #-} latest :: Monad m => Scanl m a (Maybe a) -latest = mkScanl1 (\_ x -> x) +latest = scanl1' (\_ x -> x) -- | Lift a Maybe returning function to a scan. functionM :: Monad m => (a -> m (Maybe b)) -> Scanl m a (Maybe b) @@ -570,7 +579,7 @@ toList = mkScanr (:) [] -- xn : ... : x2 : x1 : [] {-# INLINE toStreamKRev #-} toStreamKRev :: Monad m => Scanl m a (K.StreamK n a) -toStreamKRev = mkScanl (flip K.cons) K.nil +toStreamKRev = scanl' (flip K.cons) K.nil -- | Scans its input building a pure stream. -- @@ -586,12 +595,12 @@ toStreamK = mkScanr K.cons K.nil -- Definition: -- -- >>> genericLength = fmap getSum $ Scanl.foldMap (Sum . const 1) --- >>> genericLength = Scanl.mkScanl (\n _ -> n + 1) 0 +-- >>> genericLength = Scanl.scanl' (\n _ -> n + 1) 0 -- -- /Pre-release/ {-# INLINE genericLength #-} genericLength :: (Monad m, Num b) => Scanl m a b -genericLength = mkScanl (\n _ -> n + 1) 0 +genericLength = scanl' (\n _ -> n + 1) 0 -- | Determine the length of the input stream. -- @@ -620,14 +629,14 @@ maxBy cmp x y = -- {-# INLINE maximumBy #-} maximumBy :: Monad m => (a -> a -> Ordering) -> Scanl m a (Maybe a) -maximumBy cmp = mkScanl1 (maxBy cmp) +maximumBy cmp = scanl1' (maxBy cmp) -- | Determine the maximum element in a stream. -- -- Definitions: -- -- >>> maximum = Scanl.maximumBy compare --- >>> maximum = Scanl.mkScanl1 max +-- >>> maximum = Scanl.scanl1' max -- -- Same as the following but without a default maximum. The 'Max' Monoid uses -- the 'minBound' as the default maximum: @@ -636,7 +645,7 @@ maximumBy cmp = mkScanl1 (maxBy cmp) -- {-# INLINE maximum #-} maximum :: (Monad m, Ord a) => Scanl m a (Maybe a) -maximum = mkScanl1 max +maximum = scanl1' max {-# INLINE minBy #-} minBy :: (a -> a -> Ordering) -> a -> a -> a @@ -649,7 +658,7 @@ minBy cmp x y = -- {-# INLINE minimumBy #-} minimumBy :: Monad m => (a -> a -> Ordering) -> Scanl m a (Maybe a) -minimumBy cmp = mkScanl1 (minBy cmp) +minimumBy cmp = scanl1' (minBy cmp) -- | Determine the minimum element in a stream using the supplied comparison -- function. @@ -657,7 +666,7 @@ minimumBy cmp = mkScanl1 (minBy cmp) -- Definitions: -- -- >>> minimum = Scanl.minimumBy compare --- >>> minimum = Scanl.mkScanl1 min +-- >>> minimum = Scanl.scanl1' min -- -- Same as the following but without a default minimum. The 'Min' Monoid uses the -- 'maxBound' as the default maximum: @@ -666,7 +675,7 @@ minimumBy cmp = mkScanl1 (minBy cmp) -- {-# INLINE minimum #-} minimum :: (Monad m, Ord a) => Scanl m a (Maybe a) -minimum = mkScanl1 min +minimum = scanl1' min extractRange :: Range a -> Maybe (a, a) extractRange RangeNone = Nothing @@ -678,7 +687,7 @@ data Range a = RangeNone | Range !a !a -- {-# INLINE rangeBy #-} rangeBy :: Monad m => (a -> a -> Ordering) -> Scanl m a (Maybe (a, a)) -rangeBy cmp = fmap extractRange $ mkScanl step RangeNone +rangeBy cmp = fmap extractRange $ scanl' step RangeNone where @@ -689,7 +698,7 @@ rangeBy cmp = fmap extractRange $ mkScanl step RangeNone -- {-# INLINE range #-} range :: (Monad m, Ord a) => Scanl m a (Maybe (a, a)) -range = fmap extractRange $ mkScanl step RangeNone +range = fmap extractRange $ scanl' step RangeNone where @@ -1331,7 +1340,7 @@ postscanlMaybe f1 f2 = postscanl f1 (catMaybes f2) -- {-# INLINE filtering #-} filtering :: Monad m => (a -> Bool) -> Scanl m a (Maybe a) -filtering f = mkScanl step Nothing +filtering f = scanl' step Nothing where @@ -1409,7 +1418,7 @@ data Tuple'Fused a b = Tuple'Fused !a !b deriving Show {-# INLINE taking #-} taking :: Monad m => Int -> Scanl m a (Maybe a) -taking n = mkScant step initial extract +taking n = scant' step initial extract where @@ -1427,7 +1436,7 @@ taking n = mkScant step initial extract {-# INLINE dropping #-} dropping :: Monad m => Int -> Scanl m a (Maybe a) -dropping n = mkScant step initial extract +dropping n = scant' step initial extract where @@ -2028,3 +2037,14 @@ morphInner f (Scanl step initial extract final) = -- /Pre-release/ generalizeInner :: Monad m => Scanl Identity a b -> Scanl m a b generalizeInner = morphInner (return . runIdentity) + +------------------------------------------------------------------------------ +-- Deprecated +------------------------------------------------------------------------------ + +RENAME_PRIME(mkScanl,scanl) +RENAME_PRIME(mkScanlM,scanlM) +RENAME_PRIME(mkScanl1,scanl1) +RENAME_PRIME(mkScanl1M,scanl1M) +RENAME_PRIME(mkScant,scant) +RENAME_PRIME(mkScantM,scantM) diff --git a/core/src/Streamly/Internal/Data/Scanl/Window.hs b/core/src/Streamly/Internal/Data/Scanl/Window.hs index 2c4517a494..2d0e28a37e 100644 --- a/core/src/Streamly/Internal/Data/Scanl/Window.hs +++ b/core/src/Streamly/Internal/Data/Scanl/Window.hs @@ -243,7 +243,7 @@ cumulativeScan = Scanl.lmap Insert {-# INLINE incrRollingMapM #-} incrRollingMapM :: Monad m => (Maybe a -> a -> m (Maybe b)) -> Scanl m (Incr a) (Maybe b) -incrRollingMapM f = Scanl.mkScanlM f1 initial +incrRollingMapM f = Scanl.scanlM' f1 initial where @@ -260,7 +260,7 @@ incrRollingMapM f = Scanl.mkScanlM f1 initial {-# INLINE incrRollingMap #-} incrRollingMap :: Monad m => (Maybe a -> a -> Maybe b) -> Scanl m (Incr a) (Maybe b) -incrRollingMap f = Scanl.mkScanl f1 initial +incrRollingMap f = Scanl.scanl' f1 initial where @@ -367,7 +367,7 @@ incrSum = Scanl step initial extract extract -- {-# INLINE incrCount #-} incrCount :: (Monad m, Num b) => Scanl m (Incr a) b -incrCount = Scanl.mkScanl step 0 +incrCount = Scanl.scanl' step 0 where diff --git a/core/src/Streamly/Internal/Data/Stream/Transform.hs b/core/src/Streamly/Internal/Data/Stream/Transform.hs index 7512b7dd39..031030e0f0 100644 --- a/core/src/Streamly/Internal/Data/Stream/Transform.hs +++ b/core/src/Streamly/Internal/Data/Stream/Transform.hs @@ -215,7 +215,7 @@ import Fusion.Plugin.Types (Fuse(..)) import Streamly.Internal.Data.Fold.Type (Fold(..)) import Streamly.Internal.Data.Pipe.Type (Pipe(..)) import Streamly.Internal.Data.Scanl.Type (Scanl(..)) -import Streamly.Internal.Data.Scanr (Scanr(..)) +import Streamly.Internal.Data.Scan (Scan(..)) import Streamly.Internal.Data.SVar.Type (adaptState) import Streamly.Internal.Data.Time.Units (AbsTime, RelTime64) import Streamly.Internal.Data.Unbox (Unbox) @@ -284,25 +284,25 @@ pipe (Pipe consume produce initial) (Stream stream_step state) = {-# ANN type RunScanState Fuse #-} data RunScanState st sc ps = ScanConsume st sc --- | Use a lazy right 'Scanr' to transform a stream. +-- | Use a lazy right 'Scan' to transform a stream. -- -- The following example extracts the input stream up to a point where the -- running average of elements is no more than 10: -- -- >>> import Data.Maybe (fromJust) --- >>> let avg = Scanr.teeWith (/) Scanr.sum (fmap fromIntegral Scanr.length) +-- >>> let avg = Scan.teeWith (/) Scan.sum (fmap fromIntegral Scan.length) -- >>> s = Stream.enumerateFromTo 1.0 100.0 -- >>> :{ -- Stream.fold Fold.toList -- $ fmap fst -- $ Stream.takeWhile (\(_,x) -> x <= 10) --- $ Stream.scanr (Scanr.tee Scanr.identity avg) s +-- $ Stream.scanr (Scan.tee Scan.identity avg) s -- :} -- [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0] -- {-# INLINE_NORMAL scanr #-} -scanr :: Monad m => Scanr m a b -> Stream m a -> Stream m b -scanr (Scanr consume initial) (Stream stream_step state) = +scanr :: Monad m => Scan m a b -> Stream m a -> Stream m b +scanr (Scan consume initial) (Stream stream_step state) = Stream step (ScanConsume state initial) where @@ -643,7 +643,7 @@ scanWith restart (Fold fstep initial extract final) = -- -- EXPLANATION: --- >>> scanl' step z = Stream.scanl (Scanl.mkScanl step z) +-- >>> scanl' step z = Stream.scanl (Scanl.scanl' step z) -- -- Like 'map', 'scanl'' too is a one to one transformation, -- however it adds an extra element. @@ -667,7 +667,7 @@ scanWith restart (Fold fstep initial extract final) = -- Consider the following monolithic example, computing the sum and the product -- of the elements in a stream in one go using a @foldl'@: -- --- >>> foldl' step z = Stream.fold (Scanl.mkScanl step z) +-- >>> foldl' step z = Stream.fold (Scanl.scanl' step z) -- >>> foldl' (\(s, p) x -> (s + x, p * x)) (0,1) s -- (10,24) -- @@ -967,7 +967,7 @@ scanlMAfter' fstep initial done s = -- lazy expressions inside the accumulator, it is recommended that a strict -- data structure is used for accumulator. -- --- >>> scanl' step z = Stream.scanl (Scanl.mkScanl step z) +-- >>> scanl' step z = Stream.scanl (Scanl.scanl' step z) -- >>> scanl' f z xs = Stream.scanlM' (\a b -> return (f a b)) (return z) xs -- -- See also: 'usingStateT' @@ -1888,7 +1888,7 @@ reassembleBy = undefined -- Adapted from the vector package -- | --- >>> f = Scanl.mkScanl (\(i, _) x -> (i + 1, x)) (-1,undefined) +-- >>> f = Scanl.scanl' (\(i, _) x -> (i + 1, x)) (-1,undefined) -- >>> indexed = Stream.postscanl f -- >>> indexed = Stream.zipWith (,) (Stream.enumerateFrom 0) -- >>> indexedR n = fmap (\(i, a) -> (n - i, a)) . indexed @@ -1914,7 +1914,7 @@ indexed (Stream step state) = Stream step' (state, 0) -- Adapted from the vector package -- | --- >>> f n = Scanl.mkScanl (\(i, _) x -> (i - 1, x)) (n + 1,undefined) +-- >>> f n = Scanl.scanl' (\(i, _) x -> (i - 1, x)) (n + 1,undefined) -- >>> indexedR n = Stream.postscanl (f n) -- -- >>> s n = Stream.enumerateFromThen n (n - 1) @@ -2061,7 +2061,7 @@ rollingMapM f (Stream step1 state1) = Stream step (RollingMapGo state1 Nothing) -- rollingMap is a special case of an incremental sliding fold. It can be -- written as: -- --- > fld f = slidingWindow 1 (Scanl.mkScanl (\_ (x,y) -> f y x) +-- > fld f = slidingWindow 1 (Scanl.scanl' (\_ (x,y) -> f y x) -- > rollingMap f = Stream.postscan (fld f) undefined -- | Apply a function on every two successive elements of a stream. The first diff --git a/core/src/Streamly/Internal/Data/Unfold.hs b/core/src/Streamly/Internal/Data/Unfold.hs index 20e066ce92..4ece9d0aa1 100644 --- a/core/src/Streamly/Internal/Data/Unfold.hs +++ b/core/src/Streamly/Internal/Data/Unfold.hs @@ -439,7 +439,7 @@ scan (Fold s i e f) = scanWith False (Scanl s i e f) {-# DEPRECATED postscanlM' "Please use \"postscanl (Scanl.scanlM' f z)\" instead" #-} {-# INLINE_NORMAL postscanlM' #-} postscanlM' :: Monad m => (b -> a -> m b) -> m b -> Unfold m c a -> Unfold m c b -postscanlM' f z = postscanl (Scanl.mkScanlM f z) +postscanlM' f z = postscanl (Scanl.scanlM' f z) ------------------------------------------------------------------------------- -- Convert streams into unfolds diff --git a/core/src/doctest/DocTestDataStream.hs b/core/src/doctest/DocTestDataStream.hs index 8630ba4cbf..4f65b63cca 100644 --- a/core/src/doctest/DocTestDataStream.hs +++ b/core/src/doctest/DocTestDataStream.hs @@ -34,7 +34,7 @@ For APIs that have not been released yet. >>> import qualified Streamly.Internal.Control.Exception as Exception >>> import qualified Streamly.Internal.FileSystem.Path as Path ->>> import qualified Streamly.Internal.Data.Scanr as Scanr +>>> import qualified Streamly.Internal.Data.Scan as Scan >>> import qualified Streamly.Internal.Data.Scanl as Scanl >>> import qualified Streamly.Internal.Data.Fold as Fold >>> import qualified Streamly.Internal.Data.Parser as Parser diff --git a/core/streamly-core.cabal b/core/streamly-core.cabal index 071b00ab7e..29fa3ae976 100644 --- a/core/streamly-core.cabal +++ b/core/streamly-core.cabal @@ -374,7 +374,7 @@ library , Streamly.Internal.Data.Parser , Streamly.Internal.Data.ParserK , Streamly.Internal.Data.Pipe - , Streamly.Internal.Data.Scanr + , Streamly.Internal.Data.Scan -- streamly-containers (non-base) , Streamly.Internal.Data.Fold diff --git a/docs/User/Tutorials/types-and-modules(examples).md b/docs/User/Tutorials/types-and-modules(examples).md index 2c91be22c6..d0baf203ea 100644 --- a/docs/User/Tutorials/types-and-modules(examples).md +++ b/docs/User/Tutorials/types-and-modules(examples).md @@ -97,10 +97,10 @@ each number in a stream. ```haskell scan1 :: Monad m => Scanl.Scanl m Int Int -scan1 = Scanl.mkScanl (\_ x -> x * x) undefined +scan1 = Scanl.scanl' (\_ x -> x * x) undefined scan2 :: Monad m => Scanl.Scanl m Int Int -scan2 = Scanl.mkScanl (\_ x -> 3 * x) undefined +scan2 = Scanl.scanl' (\_ x -> 3 * x) undefined scan3 :: Monad m => Scanl.Scanl m Int Int scan3 = Scanl.teeWith (+) scan1 scan2 -- Compute x^2 + 3x diff --git a/src/Streamly/Internal/Data/Stream/Time.hs b/src/Streamly/Internal/Data/Stream/Time.hs index bf870adc70..435c5f6496 100644 --- a/src/Streamly/Internal/Data/Stream/Time.hs +++ b/src/Streamly/Internal/Data/Stream/Time.hs @@ -897,7 +897,7 @@ sampleBurst sampleAtEnd gap xs = -- but the tick stream should work well as long as the timer -- granularity is small enough compared to the gap. Stream.mapMaybe extract - $ Stream.scanl (Scanl.mkScanl step BurstNone) + $ Stream.scanl (Scanl.scanl' step BurstNone) $ Stream.timeIndexed $ interject (return Nothing) 0.01 (fmap Just xs) diff --git a/test/Streamly/Test/Data/Scanl/Concurrent.hs b/test/Streamly/Test/Data/Scanl/Concurrent.hs index 6141d9e534..9746b98fc0 100644 --- a/test/Streamly/Test/Data/Scanl/Concurrent.hs +++ b/test/Streamly/Test/Data/Scanl/Concurrent.hs @@ -59,10 +59,10 @@ parDemuxScan_ScanEnd concOpts = do let streamLen = 10000 evenLen = 100 demuxer i = even (i :: Int) - ref <- newIORef (Scanl.take evenLen $ Scanl.mkScanl1 (\_ x -> x)) + ref <- newIORef (Scanl.take evenLen $ Scanl.scanl1' (\_ x -> x)) let gen True = atomicModifyIORef' ref (\xs -> (fmap (const Nothing) Scanl.drain, xs)) - gen False = pure $ Scanl.mkScanl1 (\_ x -> x) + gen False = pure $ Scanl.scanl1' (\_ x -> x) inpList = [1..streamLen] inpStream = Stream.fromList inpList res <- @@ -92,7 +92,7 @@ parDemuxScan_StreamEnd :: (Scanl.Config -> Scanl.Config) -> IO () parDemuxScan_StreamEnd concOpts = do let streamLen = 10000 demuxer i = even (i :: Int) - gen _ = pure $ Scanl.mkScanl1 (\_ x -> x) + gen _ = pure $ Scanl.scanl1' (\_ x -> x) inpList = [1..streamLen] inpStream = Stream.fromList inpList res <- @@ -120,7 +120,7 @@ parDemuxScan_WorkerException concOpts = do if (x :: Int) > throwAfter then error "worker exception" else pure x) - $ Scanl.mkScanl1 (\_ x -> x) + $ Scanl.scanl1' (\_ x -> x) -- Send enough items to fill the buffer (maxBuffer 1) and block inpList = [1..100] inpStream = Stream.fromList inpList