on master help sign in
Add sampling support in folds
a12febbHarendra Kumar
src/Streamly/Internal/Data/Fold.hs+63−1
@@ -110,9 +110,12 @@ module Streamly.Internal.Data.Fold
110 , map
110 , map
111 --, lsequence
111 --, lsequence
112 , lmapM
112 , lmapM
113+ , indexed
114+
113 -- ** Filtering
115 -- ** Filtering
114 , filter
116 , filter
115 , filterM
117 , filterM
118+ , sampleFromthen
116 -- , ldeleteBy
119 -- , ldeleteBy
117 -- , luniq
120 -- , luniq
118 , lcatMaybes
121 , lcatMaybes
@@ -209,6 +212,8 @@ module Streamly.Internal.Data.Fold
209 , intervalsOf
212 , intervalsOf
210 , chunksOf
213 , chunksOf
211 , chunksBetween
214 , chunksBetween
215+ , zipWithM
216+ , zip
212
217
213 , concatSequence
218 , concatSequence
214 , concatMap
219 , concatMap
@@ -230,9 +235,11 @@ import Streamly.Internal.Data.Either.Strict
230import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
235import Streamly.Internal.Data.Maybe.Strict (Maybe'(..), toMaybe)
231import Streamly.Internal.Data.Pipe.Types (Pipe (..), PipeState(..))
236import Streamly.Internal.Data.Pipe.Types (Pipe (..), PipeState(..))
232import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
237import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3'(..))
238+import Streamly.Internal.Data.Stream.Serial (SerialT)
233
239
234import qualified Data.Map.Strict as Map
240import qualified Data.Map.Strict as Map
235import qualified Streamly.Internal.Data.Pipe.Types as Pipe
241import qualified Streamly.Internal.Data.Pipe.Types as Pipe
242+import qualified Streamly.Internal.Data.Stream.IsStream.Enumeration as Stream
236import qualified Prelude
243import qualified Prelude
237
244
238import Prelude hiding
245import Prelude hiding
@@ -241,7 +248,7 @@ import Prelude hiding
241 , notElem, maximum, minimum, head, last, tail, length, null
248 , notElem, maximum, minimum, head, last, tail, length, null
242 , reverse, iterate, init, and, or, lookup, (!!)
249 , reverse, iterate, init, and, or, lookup, (!!)
243 , scanl, scanl1, replicate, concatMap, mconcat, foldMap, unzip
250 , scanl, scanl1, replicate, concatMap, mconcat, foldMap, unzip
244− , span, splitAt, break, mapM)
251+ , span, splitAt, break, mapM, zip)
245import Streamly.Internal.Data.Fold.Types
252import Streamly.Internal.Data.Fold.Types
246
253
247------------------------------------------------------------------------------
254------------------------------------------------------------------------------
@@ -1727,6 +1734,61 @@ unzipWith f = unzipWithM (return . f)
1727unzip :: Monad m => Fold m a x -> Fold m b y -> Fold m (a,b) (x,y)
1734unzip :: Monad m => Fold m a x -> Fold m b y -> Fold m (a,b) (x,y)
1728unzip = unzipWith id
1735unzip = unzipWith id
1729
1736
1737+------------------------------------------------------------------------------
1738+-- Combining streams and folds - Zipping
1739+------------------------------------------------------------------------------
1740+
1741+-- | Zip a stream with the input of a fold using the supplied function.
1742+--
1743+-- /Unimplemented/
1744+--
1745+{-# INLINE zipWithM #-}
1746+zipWithM :: -- Monad m =>
1747+ (a -> b -> m c) -> t m a -> Fold m c x -> Fold m b x
1748+zipWithM = undefined
1749+
1750+-- | Zip a stream with the input of a fold.
1751+--
1752+-- /Unimplemented/
1753+--
1754+{-# INLINE zip #-}
1755+zip :: Monad m => t m a -> Fold m (a, b) x -> Fold m b x
1756+zip = zipWithM (curry return)
1757+
1758+-- | Pair each element of a fold input with its index, starting from index 0.
1759+--
1760+-- /Unimplemented/
1761+{-# INLINE indexed #-}
1762+indexed :: forall m a b. Monad m => Fold m (Int, a) b -> Fold m a b
1763+indexed = zip (Stream.enumerateFrom 0 :: SerialT m Int)
1764+
1765+-- | Change the predicate function of a Fold from @a -> b@ to accept an
1766+-- additional state input @(s, a) -> b@. Convenient to filter with an
1767+-- addiitonal index or time input.
1768+--
1769+-- @
1770+-- filterWithIndex = with indexed filter
1771+-- filterWithAbsTime = with timestamped filter
1772+-- filterWithRelTime = with timeIndexed filter
1773+-- @
1774+--
1775+-- /Internal/
1776+{-# INLINE with #-}
1777+with ::
1778+ (Fold m (s, a) b -> Fold m a b)
1779+ -> (((s, a) -> c) -> Fold m (s, a) b -> Fold m (s, a) b)
1780+ -> (((s, a) -> c) -> Fold m a b -> Fold m a b)
1781+with f comb g = f . comb g . map snd
1782+
1783+-- | @sampleFromthen offset stride@ samples the element at @offset@ index and
1784+-- then every element at strides of @stride@.
1785+--
1786+-- /Unimplemented/
1787+{-# INLINE sampleFromthen #-}
1788+sampleFromthen :: Monad m => Int -> Int -> Fold m a b -> Fold m a b
1789+sampleFromthen offset size =
1790+ with indexed filter (\(i, _) -> (i + offset) `mod` size == 0)
1791+
1730------------------------------------------------------------------------------
1792------------------------------------------------------------------------------
1731-- Nesting
1793-- Nesting
1732------------------------------------------------------------------------------
1794------------------------------------------------------------------------------
src/Streamly/Internal/Data/Stream/IsStream/Transform.hs+3−1
@@ -23,7 +23,7 @@ module Streamly.Internal.Data.Stream.IsStream.Transform
23 , mapM
23 , mapM
24 , smapM
24 , smapM
25
25
26− -- * Mapping Side Effects
26+ -- * Mapping Side Effects (Observation)
27 , trace
27 , trace
28 , trace_
28 , trace_
29 , tap
29 , tap
@@ -387,6 +387,8 @@ sequence m = fromStreamS $ S.sequence (toStreamS m)
387tap :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> t m a
387tap :: (IsStream t, Monad m) => FL.Fold m a b -> t m a -> t m a
388tap f xs = D.fromStreamD $ D.tap f (D.toStreamD xs)
388tap f xs = D.fromStreamD $ D.tap f (D.toStreamD xs)
389
389
390+-- XXX Remove this. It can be expressed in terms of Fold.sampleFromThen.
391+--
390-- | @tapOffsetEvery offset n@ taps every @n@th element in the stream
392-- | @tapOffsetEvery offset n@ taps every @n@th element in the stream
391-- starting at @offset@. @offset@ can be between @0@ and @n - 1@. Offset 0
393-- starting at @offset@. @offset@ can be between @0@ and @n - 1@. Offset 0
392-- means start at the first element in the stream. If the offset is outside
394-- means start at the first element in the stream. If the offset is outside