packages feed

foldl-transduce 0.1.0.1 → 0.1.2.0

raw patch · 5 files changed

+129/−10 lines, 5 filesdep +bifunctorsPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: bifunctors

API changes (from Hackage documentation)

+ Control.Foldl.Transduce: groups' :: Splitter i -> Fold u v -> Transduction' i a u -> Transduction' i a v
+ Control.Foldl.Transduce: groupsM' :: Monad m => Splitter i -> FoldM m u v -> TransductionM' m i a u -> TransductionM' m i a v
+ Control.Foldl.Transduce: type Transduction' a b r = forall x. Fold b x -> Fold a (r, x)
+ Control.Foldl.Transduce: type TransductionM' m a b r = forall x. FoldM m b x -> FoldM m a (r, x)
+ Control.Foldl.Transduce.Internal: Trio :: !a -> !b -> !c -> Trio a b c
+ Control.Foldl.Transduce.Internal: data Trio a b c
- Control.Foldl.Transduce: transduce' :: Transducer i o x -> Fold o y -> Fold i (x, y)
+ Control.Foldl.Transduce: transduce' :: Transducer i o x -> Transduction' i o x
- Control.Foldl.Transduce: transduceM' :: Monad m => TransducerM m i o x -> FoldM m o y -> FoldM m i (x, y)
+ Control.Foldl.Transduce: transduceM' :: Monad m => TransducerM m i o x -> TransductionM' m i o x

Files

CHANGELOG view
@@ -1,5 +1,10 @@-0.1.1.0-=======+# 0.1.2.0+- Added explicit bifunctors dependency.+- Added Transduce', TransduceM' type synonyms.+- Added groups', groupsM'.+++# 0.1.1.0  - Changed signatures of transduce' and transduceM'. - generalize' -> generalizeTransducer
README.md view
@@ -1,3 +1,33 @@-Stateful transducers and streaming-preserving grouping operations for the folds-in Gabriel Gonzalez's [foldl](http://hackage.haskell.org/package/foldl)-package.+## What's in this library?++Stateful transducers and streaming-preserving group operations for the folds in+Gabriel Gonzalez's [foldl](http://hackage.haskell.org/package/foldl) package.++## When to use this library?++- When you want to wrap a stateful decoder over a **Fold**. An example is+decoding UTF-8: the decoder must be stateful because a multi-byte character may+have been split across two blocks of bytes.++- When you want to tweak the stream of data that arrives into a **Fold**, but+only at certain positions. Stripping whitespace at the beginning of a text+stream, for example.++- When you want to perform group operations without breaking "streaminess",+similar to what [pipes-group](http://hackage.haskell.org/package/pipes-group)+does.++## Why use this library for grouping instead of **pipes-group**?++Grouping fold-side instead of producer-side has the advantage that, since the+results are still **Fold**s, you can combine them using **Applicative**.++Also, **Fold**s can work with sources other than **Producer**s from pipes.++Grouping fold-side has limitations as well:++- You can't perform bracketing operations like "withFile" that span the folding+of an entire group. You can do that in pipes-group.++- You have more flexibility in pipes-group to decide how to fold a group based+on previous results.
foldl-transduce.cabal view
@@ -1,5 +1,5 @@ Name: foldl-transduce-Version: 0.1.0.1+Version: 0.1.2.0 Cabal-Version: >=1.8.0.2 Build-Type: Simple License: BSD3@@ -8,7 +8,7 @@ Author: Daniel Diaz Maintainer: diaz_carrete@yahoo.com Bug-Reports: https://github.com/danidiaz/foldl-transduce/issues-Synopsis: Transducers for folds from foldl.+Synopsis: Transducers for foldl folds. Description: Stateful transducers and streaming-preserving grouping operations for the folds in the foldl package. Category: Control @@ -28,6 +28,7 @@         text          >= 0.11.2.0 && < 1.3 ,         transformers  >= 0.2.0.0  && < 0.5 ,         containers                   < 0.6 ,+        bifunctors    == 5.*               ,         semigroupoids >= 5.0               ,         foldl         >= 1.1      && < 2   ,         comonad       == 4.*
src/Control/Foldl/Transduce.hs view
@@ -10,8 +10,10 @@ module Control.Foldl.Transduce (         -- * Transducer types         Transduction +    ,   Transduction'      ,   Transducer(..)     ,   TransductionM+    ,   TransductionM'     ,   TransducerM(..)         -- * Applying transducers     ,   transduce@@ -34,7 +36,9 @@     ,   Splitter(..)         -- * Working with groups     ,   groups+    ,   groups'     ,   groupsM+    ,   groupsM'     ,   folds     ,   foldsM         -- * Splitters@@ -54,12 +58,13 @@ import Control.Comonad import Control.Foldl (Fold(..),FoldM(..)) import qualified Control.Foldl as L-import Control.Foldl.Transduce.Internal(Pair(..))+import Control.Foldl.Transduce.Internal (Pair(..),Trio(..))  {- $setup  >>> import qualified Control.Foldl as L >>> import Control.Foldl.Transduce+>>> import Control.Applicative  -} @@ -93,6 +98,12 @@ type Transduction a b = forall x. Fold b x -> Fold a x  +{-| A more general from of 'Transduction' that adds new information to the+    return value of the 'Fold'.++-}+type Transduction' a b r = forall x. Fold b x -> Fold a (r,x)+ {-| Representation of a stateful 'Transduction' with step function, an initial     accumulator, and a extraction function that returns a summary value of type     @r@. Both the step function and the extraction function may send output@@ -112,6 +123,8 @@  type TransductionM m a b = forall x. Monad m => FoldM m b x -> FoldM m a x +type TransductionM' m a b r = forall x. FoldM m b x -> FoldM m a (r,x)+ {-| Like 'Transducer', but monadic.  -}@@ -146,7 +159,7 @@ >>> L.fold (transduce' (Transducer (\_ i -> ((),[i])) () (\_ -> ('r',[]))) L.list) [1..7] ('r',[1,2,3,4,5,6,7]) -}-transduce' :: Transducer i o x -> Fold o y -> Fold i (x,y)+transduce' :: Transducer i o x -> Transduction' i o x transduce' (Transducer wstep wstate wdone) (Fold fstep fstate fdone) =     Fold step (Pair wstate fstate) done          where@@ -163,7 +176,7 @@ transduceM :: Monad m => TransducerM m i o r -> TransductionM m i o  transduceM t = fmap snd . (transduceM' t) -transduceM' :: Monad m => TransducerM m i o x -> FoldM m o y -> FoldM m i (x,y)+transduceM' :: Monad m => TransducerM m i o x -> TransductionM' m i o x transduceM' (TransducerM wstep wstate wdone) (FoldM fstep fstate fdone) =     FoldM step (liftM2 Pair wstate fstate) done          where@@ -306,6 +319,8 @@ {-| Applies a 'Transduction' to all groups detected by a 'Splitter', returning     a 'Transduction' that works over the undivided stream of inputs.		 +>>> L.fold (groups (chunksOf 2) (transduce (surround "<" ">")) L.list) "aabbccdd"+"<aa><bb><cc><dd>" -} groups :: Splitter i -> Transduction i b -> Transduction i b  groups (Splitter sstep sbegin sdone) t f =@@ -323,6 +338,42 @@         done (Pair ss (Fold fstep fstate fdone)) =              extract (fdone (foldl' fstep fstate (sdone ss))) +{-| Generalized version of 'groups' that obtains a summary value for each+    group, aggregates them into a summary value for the whole stream, and puts+    that information in the final result.		++    In practice, this function behaves like a combinaton of 'groups' and+    'folds' that works in a single pass.++>>> L.fold (groups' (chunksOf 2) L.list (\f -> transduce (surround "<" ">") (liftA2 (,) L.list f)) L.list) "aabbccdd"+(["<aa>","<bb>","<cc>","<dd>"],"<aa><bb><cc><dd>")+-}+groups' :: Splitter i +        -> Fold u v -- ^ for aggregating the @u@ values produced for each group+        -> Transduction' i a u +        -> Transduction' i a v -- ^ the resulting 'Fold' will return a summary @v@ of the stream+groups' (Splitter sstep sbegin sdone) summarizer t f =+    Fold step (Trio sbegin summarizer (t (duplicated f))) done +      where +        step (Trio ss summarizer' fs) i = +           let +               (ss', oldSplit, newSplits) = sstep ss i+               (summarizer'',fs') = foldl' +                   (\(summarizer_,fs_) split_ -> +                       let (u, renewed) = reset fs_+                       in (L.fold (duplicated summarizer_) [u], step' renewed split_))+                   (summarizer', step' fs oldSplit) +                   newSplits+           in+           Trio ss' summarizer'' fs'+        step' = L.fold . duplicated+        reset (Fold _ fstate fdone) = +           let (u,x) = fdone fstate+           in (u,t (duplicated x))+        done (Trio ss summarizer' (Fold fstep fstate fdone)) = +            let (u,extract -> x) = fdone (foldl' fstep fstate (sdone ss))+            in (L.fold summarizer' [u],x)+ groupsM :: Monad m => Splitter i -> TransductionM m i b -> TransductionM m i b groupsM (Splitter sstep sbegin sdone) t f =      FoldM step (return (Pair sbegin (t (duplicated f)))) done        @@ -340,6 +391,35 @@         done (Pair ss (FoldM fstep fstate fdone)) = do             finalf <- fdone =<< flip (foldlM fstep) (sdone ss) =<< fstate             L.foldM finalf [] ++groupsM' :: Monad m => Splitter i -> FoldM m u v -> TransductionM' m i a u -> TransductionM' m i a v +groupsM' (Splitter sstep sbegin sdone) summarizer t f =+    FoldM step (return (Trio sbegin summarizer (t (duplicated f)))) done        +    where+        step (Trio ss summarizer' fs) i = do+            let +                (ss', oldSplit, newSplits) = sstep ss i+            fs' <- step' fs oldSplit+            (summarizer'',fs'') <- foldlM step'' (summarizer',fs') newSplits+            return $! Trio ss' summarizer'' fs''++        step' = L.foldM . duplicated++        step'' = \(summarizer_, fs) is -> do+            (u,fs') <- reset fs +            u' <- L.foldM (duplicated summarizer_) [u]+            fs'' <- step' fs' is+            return $! (u',fs'') ++        reset (FoldM _ fstate fdone) = do+           (u,x) <- fdone =<< fstate +           return (u, t . duplicated $ x)++        done (Trio ss summarizer' (FoldM fstep fstate fdone)) = do+            (u,finalf) <- fdone =<< flip (foldlM fstep) (sdone ss) =<< fstate+            v <- L.foldM summarizer' [u]+            r <- L.foldM finalf []+            return (v,r)  {-| Summarizes each group detected by a 'Splitter' using a 'Fold', returning a     'Transduction' that allows a 'Fold' to accept the original ungrouped input. 
src/Control/Foldl/Transduce/Internal.hs view
@@ -1,7 +1,10 @@ module Control.Foldl.Transduce.Internal (         -- * Strict datatypes          Pair(..)+    ,   Trio(..)     ) where  data Pair a b = Pair !a !b++data Trio a b c = Trio !a !b !c