on master help sign in
Add "each" a more efficient version of foldWith
10fa995Harendra Kumar
src/Asyncly/Prelude.hs+17−2
@@ -20,7 +20,10 @@
20module Asyncly.Prelude
20module Asyncly.Prelude
21 (
21 (
22 -- * Construction
22 -- * Construction
23+ cons
24+ , nil
23− unfoldr
25+ , unfoldr
26+ , each
24 , fromHandle
27 , fromHandle
25
28
26 -- * Elimination
29 -- * Elimination
@@ -74,6 +77,7 @@ import Prelude hiding (filter, drop, dropWhile, take,
74 sum, product, elem, notElem,
77 sum, product, elem, notElem,
75 maximum, minimum, head, last,
78 maximum, minimum, head, last,
76 length)
79 length)
80+import qualified Prelude as Prelude
77import qualified System.IO as IO
81import qualified System.IO as IO
78
82
79import Asyncly.Core
83import Asyncly.Core
@@ -93,6 +97,12 @@ unfoldr step = fromStream . go
93 Nothing -> stp
97 Nothing -> stp
94 Just (a, b) -> yld a (Just (go b))
98 Just (a, b) -> yld a (Just (go b))
95
99
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+
96-- | Read lines from an IO Handle into a stream of Strings.
106-- | Read lines from an IO Handle into a stream of Strings.
97fromHandle :: (MonadIO m, Streaming t) => IO.Handle -> t m String
107fromHandle :: (MonadIO m, Streaming t) => IO.Handle -> t m String
98fromHandle h = fromStream $ go
108fromHandle h = fromStream $ go
@@ -109,6 +119,8 @@ fromHandle h = fromStream $ go
109-- Elimination
119-- Elimination
110------------------------------------------------------------------------------
120------------------------------------------------------------------------------
111
121
122+-- Parallel variants of folds?
123+
112-- | Right fold.
124-- | Right fold.
113foldr :: (Monad m, Streaming t) => (a -> b -> b) -> b -> t m a -> m b
125foldr :: (Monad m, Streaming t) => (a -> b -> b) -> b -> t m a -> m b
114foldr step acc m = go (toStream m)
126foldr step acc m = go (toStream m)
@@ -120,6 +132,7 @@ foldr step acc m = go (toStream m)
120 in (runStream m1) Nothing stop yield
132 in (runStream m1) Nothing stop yield
121
133
122-- | Right fold with a monadic step function. See 'toList' for an example use.
134-- | Right fold with a monadic step function. See 'toList' for an example use.
135+{-# INLINE foldrM #-}
123foldrM :: Streaming t => (a -> m b -> m b) -> m b -> t m a -> m b
136foldrM :: Streaming t => (a -> m b -> m b) -> m b -> t m a -> m b
124foldrM step acc m = go (toStream m)
137foldrM step acc m = go (toStream m)
125 where
138 where
@@ -276,7 +289,7 @@ head m =
276 yield a _ = return (Just a)
289 yield a _ = return (Just a)
277 in (runStream (toStream m)) Nothing stop yield
290 in (runStream (toStream m)) Nothing stop yield
278
291
279−-- | Extract the first element of the stream, if any.
292+-- | Extract the last element of the stream, if any.
280last :: (Streaming t, Monad m) => t m a -> m (Maybe a)
293last :: (Streaming t, Monad m) => t m a -> m (Maybe a)
281last m = go (toStream m)
294last m = go (toStream m)
282 where
295 where
@@ -342,6 +355,8 @@ maximum m = go Nothing (toStream m)
342-- Transformation
355-- Transformation
343------------------------------------------------------------------------------
356------------------------------------------------------------------------------
344
357
358+-- XXX Parallel variants of these? mapMWith et al. sequenceWith.
359+
345-- | Apply a monadic action to each element of the stream and replace it with
360-- | Apply a monadic action to each element of the stream and replace it with
346-- the result.
361-- the result.
347mapM :: (Streaming t, Monad m) => (a -> m b) -> t m a -> t m b
362mapM :: (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
53 , fromSVar
53 , fromSVar
54
54
55 -- * Elimination
55 -- * Elimination
56+ , cons
57+ , nil
56 , streamFold
58 , streamFold
57 , runStreaming
59 , runStreaming
58 , toSVar
60 , toSVar
@@ -77,6 +79,7 @@ module Asyncly.Streams
77 , (<|)
79 , (<|)
78
80
79 -- * Fold Utilities
81 -- * Fold Utilities
82+ -- $foldutils
80 , foldWith
83 , foldWith
81 , foldMapWith
84 , foldMapWith
82 , forEachWith
85 , forEachWith
@@ -740,6 +743,12 @@ zippingAsync x = x
740-- Constructing a stream
743-- Constructing a stream
741------------------------------------------------------------------------------
744------------------------------------------------------------------------------
742
745
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+
743-- | Build a stream from its church encoding. The function passed maps
752-- | Build a stream from its church encoding. The function passed maps
744-- directly to the underlying representation of the stream type. The second
753-- directly to the underlying representation of the stream type. The second
745-- parameter to the function is the "yield" function yielding a value and the
754-- 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)
865-- Fold Utilities
874-- Fold Utilities
866------------------------------------------------------------------------------
875------------------------------------------------------------------------------
867
876
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]@
869{-# INLINABLE foldWith #-}
886{-# INLINABLE foldWith #-}
870−foldWith :: (Monoid b, Foldable t) => (a -> b -> b) -> t a -> b
887+foldWith :: (Streaming t, Foldable f)
888+ => (t m a -> t m a -> t m a) -> f (t m a) -> t m a
871−foldWith f = foldr f mempty
889+foldWith f = foldr f nil
872
890
873−-- | Fold a 'Foldable' container using a function that is a composition of the
891+-- | Like 'foldMap' but allows you to specify a binary sum style composition
874−-- two arguments.
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]@
875{-# INLINABLE foldMapWith #-}
896{-# INLINABLE foldMapWith #-}
876−foldMapWith :: (Monoid b, Foldable t) =>
897+foldMapWith :: (Streaming t, Foldable f)
877− (b1 -> b -> b) -> (a -> b1) -> t a -> b
898+ => (t m b -> t m b -> t m b) -> (a -> t m b) -> f a -> t m b
878−foldMapWith f g = foldr (f . g) mempty
899+foldMapWith f g = foldr (f . g) nil
879
900
880−-- | Fold a 'Foldable' container using a function that is a composition of the
901+-- | Like 'foldMapWith' but with the last two arguments reversed i.e. the
881−-- first and the third argument.
902+-- monadic streaming function is the last argument.
882{-# INLINABLE forEachWith #-}
903{-# INLINABLE forEachWith #-}
883−forEachWith :: (Monoid b, Foldable t) =>
904+forEachWith :: (Streaming t, Foldable f)
884− (b1 -> b -> b) -> t a -> (a -> b1) -> b
905+ => (t m b -> t m b -> t m b) -> f a -> (a -> t m b) -> t m b
885−forEachWith f xs g = foldr (f . g) mempty xs
906+forEachWith f xs g = foldr (f . g) nil xs