on master help sign in
Add "each" a more efficient version of foldWith

Also update the fold utilities foldWith and friends

commit10fa995972f4a8cbaad1139a2337de5bd68dabf6 authorHarendra Kumar <harendra.kumar@gmail.com> dateTue 31 Oct 2017, 15:21 (9 years ago) parent2d3ccad
2 files changed+51−15
src/Asyncly/Prelude.hs+17−2 src/Asyncly/Streams.hs+34−13
src/Asyncly/Prelude.hs+17−2
@@ -20,7 +20,10 @@
2020module Asyncly.Prelude
2121 (
2222 -- * Construction
23− unfoldr
23+ cons
24+ , nil
25+ , unfoldr
26+ , each
2427 , fromHandle
2528
2629 -- * Elimination
@@ -74,6 +77,7 @@ import Prelude hiding (filter, drop, dropWhile, take,
7477 sum, product, elem, notElem,
7578 maximum, minimum, head, last,
7679 length)
80+import qualified Prelude as Prelude
7781import qualified System.IO as IO
7882
7983import Asyncly.Core
@@ -93,6 +97,12 @@ unfoldr step = fromStream . go
9397 Nothing -> stp
9498 Just (a, b) -> yld a (Just (go b))
9599
100+-- XXX need eachInterleaved, eachAsync, eachParallel
101+-- | Same as @foldWith (<>)@ but more efficient.
102+{-# INLINE each #-}
103+each :: (Foldable f, Streaming t) => f a -> t m a
104+each xs = Prelude.foldr cons nil xs
105+
96106-- | Read lines from an IO Handle into a stream of Strings.
97107fromHandle :: (MonadIO m, Streaming t) => IO.Handle -> t m String
98108fromHandle h = fromStream $ go
@@ -109,6 +119,8 @@ fromHandle h = fromStream $ go
109119-- Elimination
110120------------------------------------------------------------------------------
111121
122+-- Parallel variants of folds?
123+
112124-- | Right fold.
113125foldr :: (Monad m, Streaming t) => (a -> b -> b) -> b -> t m a -> m b
114126foldr step acc m = go (toStream m)
@@ -120,6 +132,7 @@ foldr step acc m = go (toStream m)
120132 in (runStream m1) Nothing stop yield
121133
122134-- | Right fold with a monadic step function. See 'toList' for an example use.
135+{-# INLINE foldrM #-}
123136foldrM :: Streaming t => (a -> m b -> m b) -> m b -> t m a -> m b
124137foldrM step acc m = go (toStream m)
125138 where
@@ -276,7 +289,7 @@ head m =
276289 yield a _ = return (Just a)
277290 in (runStream (toStream m)) Nothing stop yield
278291
279−-- | Extract the first element of the stream, if any.
292+-- | Extract the last element of the stream, if any.
280293last :: (Streaming t, Monad m) => t m a -> m (Maybe a)
281294last m = go (toStream m)
282295 where
@@ -342,6 +355,8 @@ maximum m = go Nothing (toStream m)
342355-- Transformation
343356------------------------------------------------------------------------------
344357
358+-- XXX Parallel variants of these? mapMWith et al. sequenceWith.
359+
345360-- | Apply a monadic action to each element of the stream and replace it with
346361-- the result.
347362mapM :: (Streaming t, Monad m) => (a -> m b) -> t m a -> t m b
src/Asyncly/Streams.hs+34−13
@@ -53,6 +53,8 @@ module Asyncly.Streams
5353 , fromSVar
5454
5555 -- * Elimination
56+ , cons
57+ , nil
5658 , streamFold
5759 , runStreaming
5860 , toSVar
@@ -77,6 +79,7 @@ module Asyncly.Streams
7779 , (<|)
7880
7981 -- * Fold Utilities
82+ -- $foldutils
8083 , foldWith
8184 , foldMapWith
8285 , forEachWith
@@ -740,6 +743,12 @@ zippingAsync x = x
740743-- Constructing a stream
741744------------------------------------------------------------------------------
742745
746+cons :: (Streaming t) => a -> t m a -> t m a
747+cons a r = fromStream $ Stream $ \_ _ yld -> yld a (Just (toStream r))
748+
749+nil :: Streaming t => t m a
750+nil = fromStream $ Stream $ \_ stp _ -> stp
751+
743752-- | Build a stream from its church encoding. The function passed maps
744753-- directly to the underlying representation of the stream type. The second
745754-- parameter to the function is the "yield" function yielding a value and the
@@ -865,21 +874,33 @@ m1 <| m2 = fromStream $ parLeft (toStream m1) (toStream m2)
865874-- Fold Utilities
866875------------------------------------------------------------------------------
867876
868−-- | Fold a 'Foldable' container using the given function.
877+-- $foldutils
878+-- These utilities are designed to pass the first argument as one of the sum
879+-- style composition operators (i.e. '<>', '<=>', '<|', '<|>') to conveniently
880+-- fold a container using any style of stream composition.
881+
882+-- | Like the 'Prelude' 'fold' but allows you to specify a binary sum style
883+-- stream composition operator to fold a container of streams.
884+--
885+-- @foldWith (<>) $ map return [1..3]@
869886{-# INLINABLE foldWith #-}
870−foldWith :: (Monoid b, Foldable t) => (a -> b -> b) -> t a -> b
871−foldWith f = foldr f mempty
887+foldWith :: (Streaming t, Foldable f)
888+ => (t m a -> t m a -> t m a) -> f (t m a) -> t m a
889+foldWith f = foldr f nil
872890
873−-- | Fold a 'Foldable' container using a function that is a composition of the
874−-- two arguments.
891+-- | Like 'foldMap' but allows you to specify a binary sum style composition
892+-- operator to fold a container of streams. Maps a monadic streaming action on
893+-- the container before folding it.
894+--
895+-- @foldMapWith (<>) return [1..3]@
875896{-# INLINABLE foldMapWith #-}
876−foldMapWith :: (Monoid b, Foldable t) =>
877− (b1 -> b -> b) -> (a -> b1) -> t a -> b
878−foldMapWith f g = foldr (f . g) mempty
897+foldMapWith :: (Streaming t, Foldable f)
898+ => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
899+foldMapWith f g = foldr (f . g) nil
879900
880−-- | Fold a 'Foldable' container using a function that is a composition of the
881−-- first and the third argument.
901+-- | Like 'foldMapWith' but with the last two arguments reversed i.e. the
902+-- monadic streaming function is the last argument.
882903{-# INLINABLE forEachWith #-}
883−forEachWith :: (Monoid b, Foldable t) =>
884− (b1 -> b -> b) -> t a -> (a -> b1) -> b
885−forEachWith f xs g = foldr (f . g) mempty xs
904+forEachWith :: (Streaming t, Foldable f)
905+ => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b
906+forEachWith f xs g = foldr (f . g) nil xs