packages feed

streaming 0.1.0.1 → 0.1.0.3

raw patch · 4 files changed

+153/−30 lines, 4 files

Files

Streaming.hs view
@@ -13,6 +13,7 @@    maps,    maps',    mapsM,+   distribute,        -- * Inspecting a stream    inspect,@@ -65,8 +66,17 @@ > Stream (Of a) m (Stream (Of a) m r) -- the effectful splitting of a producer >                                        -- i.e. an effectful ([a],[a]) or rather ([a],([a],r)) > Stream (Stream (Of a) m) m r        -- successive, segmentation of a producer-                                         -- i.e. [[a]], or ([a],([a],([a]... r)))-    and so on. But of course any functor can be used.+>                                        -- i.e. [[a]], or ([a],([a],([a]... r)))++    and so on. But of course any functor can be used. So, for example, ++> Stream ((->) input) m result++    is a simple @Consumer input m result@ or @Parser input m result@ type. And so on.+    See e.g. http://www.haskellforall.com/2012/07/purify-code-using-free-monads.html ,+    http://www.haskellforall.com/2012/07/free-monad-transformers.html and similar+    literature.+      To avoid breaking reasoning principles, the constructors      should not be used directly. A pattern-match should go by way of 'inspect' 
Streaming/Internal.hs view
@@ -15,6 +15,7 @@     , intercalates      , iterT      , iterTM +          -- * Inspecting a stream step by step     , inspect @@ -22,6 +23,7 @@     -- * Transforming streams     , maps      , mapsM +    , distribute          -- *  Splitting streams     , chunksOf @@ -128,7 +130,7 @@   liftIO = Delay . liftM Return . liftIO   {-# INLINE liftIO #-} --- | Map a stream to its church encoding; compare list 'foldr'+-- | Map a stream to its church encoding; compare @Data.List.foldr@ destroy    :: (Functor f, Monad m) =>      Stream f m r -> (f b -> b) -> (m b -> b) -> (r -> b) -> b@@ -139,7 +141,7 @@     Step fs  -> construct (fmap loop fs) {-# INLINABLE destroy #-} --- | Reflect a church-encoded stream; cp. GHC.Exts.build+-- | Reflect a church-encoded stream; cp. @GHC.Exts.build@ construct   :: (forall b . (f b -> b) -> (m b -> b) -> (r -> b) -> b) ->  Stream f m r construct = \phi -> phi Step Delay Return@@ -162,7 +164,8 @@     Step fs  -> return (Right fs) {-# INLINABLE inspect #-}     -{-| Build a @Stream@ by unfolding steps starting from a seed. +{-| Build a @Stream@ by unfolding steps starting from a seed. See also+    the specialized 'Streaming.Prelude.unfoldr' in the prelude.  > unfold inspect = id -- modulo the quotient we work with > unfold Pipes.next :: Monad m => Producer a m r -> Stream ((,) a) m r@@ -201,8 +204,10 @@ {-# INLINABLE mapsM #-}  -+{-| Interpolate a layer at each segment. This specializes to e.g. +> intercalates :: (Monad m, Functor f) => Stream f m () -> Stream (Stream f m) m r -> Stream f m r+-} intercalates :: (Monad m, Monad (t m), MonadTrans t) =>      t m a -> Stream (t m) m b -> t m b intercalates sep = go0@@ -222,6 +227,10 @@                 go1 f' {-# INLINABLE intercalates #-} +{-| Specialized fold++> iterTM alg stream = destroy stream alg (join . lift) return+-} iterTM ::   (Functor f, Monad m, MonadTrans t,    Monad (t m)) =>@@ -229,18 +238,31 @@ iterTM out stream = destroy stream out (join . lift) return {-# INLINE iterTM #-} +{-| Specialized fold++> iterT alg stream = destroy stream alg join return+-} iterT ::   (Functor f, Monad m) => (f (m a) -> m a) -> Stream f m a -> m a iterT out stream = destroy stream out join return {-# INLINE iterT #-} +{-| This specializes to the more transparent case:++> concats :: (Monad m, Functor f) => Stream (Stream f m) m r -> Stream f m r++    Thus dissolving the segmentation into @Stream f m@ layers.++> concats stream = destroy stream join (join . lift) return+-} concats ::     (MonadTrans t, Monad (t m), Monad m) =>     Stream (t m) m a -> t m a concats stream = destroy stream join (join . lift) return {-# INLINE concats #-} -+-- | Split a succession of layers after some number, returning a streaming or+--   effectful pair. split :: (Monad m, Functor f) => Int -> Stream f m r -> Stream f m (Stream f m r) split = loop where   loop !n stream @@ -253,6 +275,7 @@           _ -> Step (fmap (loop (n-1)) fs) {-# INLINABLE split #-}                         +-- | Break a stream into substreams each with n functorial layers.  chunksOf :: (Monad m, Functor f) => Int -> Stream f m r -> Stream (Stream f m) m r chunksOf n0 = loop where   loop stream = case stream of@@ -260,3 +283,36 @@     Delay m        -> Delay (liftM loop m)     Step fs        -> Step $ Step $ fmap (fmap loop . split n0) fs {-# INLINABLE chunksOf #-}          ++{- | Make it possible to \'run\' the underlying transformed monad. A simple+     minded example might be: ++> debugFibs = flip runStateT 1 $ distribute $ loop 1 where+>   loop n = do+>     S.yield n+>     s <- lift get +>     liftIO $ putStr "state is: " >> print s+>     lift $ put (s + n :: Int)+>     loop s++>>> S.print $  S.take 4 $ S.drop 4 $ debugFibs+state is: 1+state is: 2+state is: 3+state is: 5+5+state is: 8+8+state is: 13+13+state is: 21+21++-}+distribute :: (Monad m, Functor f, MonadTrans t, MFunctor t, Monad (t (Stream f m)))+           => Stream f (t m) r -> t (Stream f m) r+distribute = loop where+  loop stream = case stream of +    Return r    -> lift $ Return r+    Delay tmstr -> hoist lift tmstr >>= distribute+    Step fstr   -> join $ lift (Step (fmap (Return . distribute) fstr))
Streaming/Prelude.hs view
@@ -149,7 +149,13 @@  {-| Apply an action to all values flowing downstream -> let debug str = chain print str+>>> let debug str = chain print str+>>> S.product (debug (S.each [2..4])) >>= print+2+3+4+24+ -} chain :: Monad m => (a -> m ()) -> Stream (Of a) m r -> Stream (Of a) m r chain f str = for str $ \a -> do@@ -157,7 +163,14 @@     yield a {-# INLINE chain #-} +{-| Make a stream of traversable containers into a stream of their separate elements +>>> Streaming.print $ concat (each ["hi","ho"])+'h'+'i'+'h'+'o'+-}  concat :: (Monad m, Foldable f) => Stream (Of (f a)) m r -> Stream (Of a) m r concat str = for str each@@ -209,7 +222,13 @@ -- each  -- --------------- --- | Stream the elements of a foldable container.+{- | Stream the elements of a foldable container.++>>> S.print $ S.each [1..3]+1+2+3+-} each :: (Monad m, Foldable.Foldable f) => f a -> Stream (Of a) m () each = Foldable.foldr (\a p -> Step (a :> p)) (Return ()) {-# INLINE each #-}@@ -351,8 +370,8 @@     See also the more general 'iterTM' in the 'Streaming' module      and the still more general 'destroy' -foldrT (\a p -> Pipes.yield a >> p) :: Monad m => Stream (Of a) m r -> Producer a m r-foldrT (\a p -> Conduit.yield a >> p) :: Monad m => Stream (Of a) m r -> Conduit a m r+> foldrT (\a p -> Pipes.yield a >> p) :: Monad m => Stream (Of a) m r -> Producer a m r+> foldrT (\a p -> Conduit.yield a >> p) :: Monad m => Stream (Of a) m r -> Conduit a m r  -} @@ -493,12 +512,20 @@      There is no reason to prefer @inspect@ since, if the @Right@ case is exposed,       the first element in the pair will have been evaluated to whnf. -next :: Monad m => Stream (Of a) m r -> m (Either r (a, Stream (Of a) m r))-inspect :: Monad m => Stream (Of a) m r -> m (Either r (Of a (Stream (Of a) m r)))+> next :: Monad m => Stream (Of a) m r -> m (Either r (a, Stream (Of a) m r))+> inspect :: Monad m => Stream (Of a) m r -> m (Either r (Of a (Stream (Of a) m r))) -IOStreams.unfoldM (liftM (either (const Nothing) Just) . next) :: Stream (Of a) IO b -> IO (InputStream a)-Conduit.unfoldM (liftM (either (const Nothing) Just) . next) :: Stream (Of a) m r -> Source a m r+     Interoperate with @pipes@ producers thus: +> Pipes.unfoldr Stream.next :: Stream (Of a) m r -> Producer a m r+> Stream.unfoldr Pipes.next :: Producer a m r -> Stream (Of a) m r +     +     Similarly: ++> IOStreams.unfoldM (liftM (either (const Nothing) Just) . next) :: Stream (Of a) IO b -> IO (InputStream a)+> Conduit.unfoldM (liftM (either (const Nothing) Just) . next)   :: Stream (Of a) m r -> Source a m r++     But see 'uncons' -} next :: Monad m => Stream (Of a) m r -> m (Either r (a, Stream (Of a) m r)) next = loop where@@ -512,8 +539,8 @@ {-| Inspect the first item in a stream of elements, without a return value.      Useful for unfolding into another streaming type. -IOStreams.unfoldM uncons :: Stream (Of a) IO b -> IO (InputStream a)-Conduit.unfoldM uncons :: Stream (Of o) m r -> Conduit.Source m o+> IOStreams.unfoldM uncons :: Stream (Of a) IO b -> IO (InputStream a)+> Conduit.unfoldM uncons   :: Stream (Of o) m r -> Conduit.Source m o  -} uncons :: Monad m => Stream (Of a) m () -> m (Maybe (a, Stream (Of a) m ()))@@ -568,13 +595,14 @@ -- replicate  -- --------------- +-- | Repeat an element several times replicate :: Monad m => Int -> a -> Stream (Of a) m () replicate n a = loop n where   loop 0 = Return ()   loop m = Step (a :> loop (m-1)) {-# INLINEABLE replicate #-} --- | Repeat an action, streaming the results.+-- | Repeat an action several times, streaming the results. replicateM :: Monad m => Int -> m a -> Stream (Of a) m () replicateM n ma = loop n where    loop 0 = Return ()@@ -587,6 +615,13 @@ {-| Strict left scan, streaming, e.g. successive partial results.  > Control.Foldl.purely scan :: Monad m => Fold a b -> Stream (Of a) m r -> Stream (Of b) m r++>>> Streaming.print $ Foldl.purely Streaming.scan Foldl.list $ each [3..5]+[]+[3]+[3,4]+[3,4,5]+ -} scan :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Stream (Of a) m r -> Stream (Of b) m r scan step begin done = loop begin@@ -625,10 +660,13 @@ -- sequence -- --------------- --- | Like the 'Data.List.sequence' but streaming. The result type is a--- stream of a\'s, but is not accumulated; the effects of the elements--- of the original stream are interleaved in the resulting stream.+{-| Like the 'Data.List.sequence' but streaming. The result type is a+    stream of a\'s, /but is not accumulated/; the effects of the elements+    of the original stream are interleaved in the resulting stream. Compare: +> sequence :: Monad m =>       [m a]           -> m [a]+> sequence :: Monad m => Stream (Of (m a)) m r -> Stream (Of a) m r+-} sequence :: Monad m => Stream (Of (m a)) m r -> Stream (Of a) m r sequence = loop where   loop stream = case stream of@@ -751,8 +789,8 @@     more general 'unfold' would require dealing with the left-strict pair     we are using. -unfoldr Pipes.next :: Monad m => Producer a m r -> Stream (Of a) m r-unfold (curry (:>) . Pipes.next) :: Monad m => Producer a m r -> Stream (Of a) m r+> unfoldr Pipes.next :: Monad m => Producer a m r -> Stream (Of a) m r+> unfold (curry (:>) . Pipes.next) :: Monad m => Producer a m r -> Stream (Of a) m r  -} unfoldr :: Monad m 
streaming.cabal view
@@ -1,12 +1,32 @@ name:                streaming-version:             0.1.0.1+version:             0.1.0.3 cabal-version:       >=1.10 build-type:          Simple-synopsis:            A general free monad transformer optimized for streaming applications.-description:         Stream is an optimized variant of FreeT.-                     It can be used wherever FreeT is used, but is focused-                     on employment with functors like '((,) a)' which generate-                     effectful sequences or \"producers\"+synopsis:            A general free monad transformer +                     optimized for streaming applications.+                     +description:         `Stream` can be used wherever `FreeT` is used. The compiler+                     is better able to optimize operations written in+                     terms of `Stream`.+                     .+                     An associated prelude of functions, closely following +                     @Pipes.Prelude@ is focused on on employment with a base +                     functor like @((,) a)@ (here called @Of a@) which generates+                     effectful sequences or producers - @Pipes.Producer@, +                     @Conduit.Source@, @IOStreams.InputStream@, @IOStreams.Generator@+                     and the like.+                     .+                     Interoperation with `pipes` is accomplished with this isomorphism:+                     .  +                     > Pipes.unfoldr Streaming.next :: Stream (Of a) m r -> Producer a m r+                     > Stream.unfoldr Pipes.next    :: Producer a m r -> Stream (Of a) m r+                     .+                     Exit to `conduit` and `iostreams` is thus:+                     .+                     > Conduit.unfoldM Streaming.uncons   :: Stream (Of a) m ()  -> Source m a+                     > IOStreams.unfoldM Streaming.uncons :: Stream (Of a) IO () -> InputStream a+                     +                      license:             BSD3 license-file:        LICENSE author:              michaelt@@ -39,7 +59,6 @@                      , ghc-prim    default-language:  Haskell2010-  ghc-options:      -O2