@@ -278,6 +278,7 @@ module Streamly.Fold
278 , partitionByM
278 , partitionByM
279 , partitionBy
279 , partitionBy
282 -- ** Unzipping
283 -- ** Unzipping
@@ -307,7 +308,7 @@ import Data.Maybe (fromJust, isJust)
307import Foreign.Storable (Storable(..))
308import Foreign.Storable (Storable(..))
308import Prelude
309import Prelude
309 hiding (filter, drop, dropWhile, take, takeWhile, zipWith, foldr,
310 hiding (filter, drop, dropWhile, take, takeWhile, zipWith, foldr,
310− foldl, map, mapM, mapM_, sequence, all, any, sum, product, elem,
311+ foldl, map, mapM_, sequence, all, any, sum, product, elem,
311 notElem, maximum, minimum, head, last, tail, length, null,
312 notElem, maximum, minimum, head, last, tail, length, null,
312 reverse, iterate, init, and, or, lookup, foldr1, (!!),
313 reverse, iterate, init, and, or, lookup, foldr1, (!!),
313 scanl, scanl1, replicate, concatMap, mconcat, foldMap, unzip,
314 scanl, scanl1, replicate, concatMap, mconcat, foldMap, unzip,
@@ -1726,10 +1727,9 @@ partitionBy f = partitionByM (return . f)
1726-- demux f kv = Fold step begin done
1727-- demux f kv = Fold step begin done
1730+-- | Split the input stream based on a key field and fold each split using a
1729−-- | Demultiplex to multiple consumers without collecting the results. Useful
1731+-- specific fold without collecting the results. Useful for cases like protocol
1730−-- to run different effectful computations depending on the value of the stream
1732+-- handlers to handle different type of packets.
1731−-- elements, for example handling network packets of different types using
1732−-- different handlers.
@@ -1748,6 +1748,8 @@ partitionBy f = partitionByM (return . f)
1751demux_ :: (Monad m, Ord k) => Map k (Fold m a ()) -> Fold m (k, a) ()
1753demux_ :: (Monad m, Ord k) => Map k (Fold m a ()) -> Fold m (k, a) ()
1752demux_ kv = Fold step initial extract
1754demux_ kv = Fold step initial extract
@@ -1764,6 +1766,34 @@ demux_ kv = Fold step initial extract
1764 initial' >>= \x -> step' x a >>= extract'
1766 initial' >>= \x -> step' x a >>= extract'
1765 extract = return
1767 extract = return
1769+-- | Split the input stream based on a key field and fold each split using the
1770+-- given fold. Useful for map/reduce, bucketizing the input in different bins
1771+-- or for generating histograms.
1774+-- > let input = S.fromList [(\"ONE",1),(\"ONE",1.1),(\"TWO",2), (\"TWO",2.2)]
1775+-- in FL.foldl' (FL.classify FL.toListRev) input
1776+-- fromList [(\"ONE",[1.1,1.0]),(\"TWO",[2.2,2.0])]
1780+classify :: (Monad m, Ord k) => Fold m a b -> Fold m (k, a) (Map k b)
1781+classify (Fold step initial extract) = Fold step' initial' extract'
1785+ initial' = return Map.empty
1787+ case Map.lookup k kv of
1791+ return $ Map.insert k r kv
1794+ return $ Map.insert k r kv
1795+ extract' = mapM extract
1767------------------------------------------------------------------------------
1797------------------------------------------------------------------------------
1768-- Unzipping
1798-- Unzipping
1769------------------------------------------------------------------------------
1799------------------------------------------------------------------------------