Safe Haskell  SafeInferred 

Language  Haskell98 
This module builds on module Control.Foldl, adding stateful transducers and grouping operations.
 type Transduction a b = forall x. Fold b x > Fold a x
 type Transduction' a b r = forall x. Fold b x > Fold a (r, x)
 data Transducer i o r = forall x . Transducer (x > i > (x, [o], [[o]])) x (x > (r, [o], [[o]]))
 class ToTransducer t where
 toTransducer :: t i o r > Transducer i o r
 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)
 data TransducerM m i o r = forall x . TransducerM (x > i > m (x, [o], [[o]])) (m x) (x > m (r, [o], [[o]]))
 class ToTransducerM m t where
 toTransducerM :: t i o r > TransducerM m i o r
 transduce :: ToTransducer t => t i o s > Transduction i o
 transduce' :: ToTransducer t => t i o s > Transduction' i o s
 transduceM :: (Monad m, ToTransducerM m t) => t i o s > TransductionM m i o
 transduceM' :: (Monad m, ToTransducerM m t) => t i o s > TransductionM' m i o s
 transduceK :: Monad m => (i > m [o]) > TransductionM m i o
 folds :: ToTransducer t => t a b s > Fold b c > Transduction a c
 folds' :: ToTransducer t => t a b s > Fold b c > Transduction' a c s
 foldsM :: (Applicative m, Monad m, ToTransducerM m t) => t a b s > FoldM m b c > TransductionM m a c
 foldsM' :: (Applicative m, Monad m, ToTransducerM m t) => t a b s > FoldM m b c > TransductionM' m a c s
 type Infinite e = Cofree Identity e
 newtype ReifiedTransduction a b = ReifiedTransduction {
 getTransduction :: Transduction a b
 groups :: ToTransducer t => t a b s > Infinite (ReifiedTransduction b c) > Transduction a c
 evenly :: Transduction b c > Infinite (ReifiedTransduction b c)
 bisect :: ToTransducer t => t a b s > Transduction b c > Transduction b c > Transduction a c
 type Moore a b = Cofree ((>) a) b
 newtype ReifiedTransduction' a b r = ReifiedTransduction' {
 getTransduction' :: Transduction' a b r
 groups' :: ToTransducer t => t a b s > Fold u v > Moore u (ReifiedTransduction' b c u) > Transduction' a c (s, v)
 evenly' :: Transduction' b c u > Moore u (ReifiedTransduction' b c u)
 newtype ReifiedTransductionM m a b = ReifiedTransductionM {
 getTransductionM :: TransductionM m a b
 groupsM :: (Monad m, ToTransducerM m t) => t a b s > Infinite (ReifiedTransductionM m b c) > TransductionM m a c
 evenlyM :: TransductionM m b c > Infinite (ReifiedTransductionM m b c)
 bisectM :: ToTransducerM m t => t a b s > TransductionM m b c > TransductionM m b c > TransductionM m a c
 newtype ReifiedTransductionM' m a b r = ReifiedTransductionM' {
 getTransductionM' :: TransductionM' m a b r
 groupsM' :: (Monad m, ToTransducerM m t) => t a b s > FoldM m u v > Moore u (ReifiedTransductionM' m b c u) > TransductionM' m a c (s, v)
 evenlyM' :: TransductionM' m b c u > Moore u (ReifiedTransductionM' m b c u)
 ignore :: Transducer a b ()
 surround :: (Traversable p, Traversable s) => p a > s a > Transducer a a ()
 surroundIO :: (Traversable p, Traversable s, Functor m, MonadIO m) => m (p a) > m (s a) > TransducerM m a a ()
 chunksOf :: Int > Transducer a a ()
 splitAt :: Int > Transducer a a ()
 chunkedSplitAt :: StableFactorialMonoid m => Int > Transducer m m ()
 splitWhen :: (a > Bool) > Transducer a a ()
 splitLast :: Transducer a a (Maybe a)
 chunkedStripPrefix :: (LeftGCDMonoid i, StableFactorialMonoid i, Traversable t, Monad m) => t i > TransducerM (ExceptT ([i], Maybe i) m) i i ()
 foldify :: Transducer i o s > Fold i s
 foldifyM :: Functor m => TransducerM m i o s > FoldM m i s
 condense :: Fold a r > Transducer a r r
 condenseM :: Applicative m => FoldM m a r > TransducerM m a r r
 hoistTransducer :: Monad m => (forall a. m a > n a) > TransducerM m i o s > TransducerM n i o s
 quiesce :: Monad m => FoldM (ExceptT e m) a r > FoldM m a (Either e r)
 quiesceWith :: (Functor m, Monad m) => FoldM m a v > FoldM (ExceptT e m) a r > FoldM m a (Either (e, v) r)
 hoistFold :: Monad m => (forall a. m a > n a) > FoldM m i r > FoldM n i r
 module Data.Functor.Extend
 module Control.Foldl
 module Control.Comonad.Cofree
Transducer types
type Transduction a b = forall x. Fold b x > Fold a x Source
A (possibly stateful) transformation on the inputs of a Fold
.
Functions constructed with combinators like premap
or handles
from
Control.Foldl also typecheck as a Transduction
.
type Transduction' a b r = forall x. Fold b x > Fold a (r, x) Source
A more general from of Transduction
that adds new information to the
return value of the Fold
.
data Transducer i o r Source
A stateful process that transforms a stream of inputs into a stream of outputs, and may optionally demarcate groups in the stream of outputs.
Composed of a step function, an initial state, and a extraction function.
The step function returns a triplet of:
 The new internal state.
 List of outputs belonging to the last segment detected in the previous step.
A list of lists of outputs belonging to segments detected in the current step. If the list is empty, that means no splitting has taken place in the current step.
Transducer
s that do not perform grouping never return anything other than[]
here. In effect, they treat the whole stream as a single group.The extraction function returns the
Transducer
s own result value, as well as any pending output.
forall x . Transducer (x > i > (x, [o], [[o]])) x (x > (r, [o], [[o]])) 
ToTransducer Transducer  
Monad m => ToTransducerM m Transducer  
Bifunctor (Transducer i)  
Functor (Transducer i o)  
Comonad (Transducer i o)  
Extend (Transducer i o) 
class ToTransducer t where Source
Helps converting monadic transducers (over Identity
) into pure ones.
toTransducer :: t i o r > Transducer i o r Source
Monadic transducer types
type TransductionM m a b = forall x. Monad m => FoldM m b x > FoldM m a x Source
Like Transduction
, but works on monadic Fold
s.
type TransductionM' m a b r = forall x. FoldM m b x > FoldM m a (r, x) Source
Like Transduction'
, but works on monadic Fold
s.
data TransducerM m i o r Source
Like Transducer
, but monadic.
forall x . TransducerM (x > i > m (x, [o], [[o]])) (m x) (x > m (r, [o], [[o]])) 
(~) (* > *) m m' => ToTransducerM m (TransducerM m')  
ToTransducer (TransducerM Identity)  
(Functor m, Monad m) => Bifunctor (TransducerM m i)  
Monad m => Functor (TransducerM m i o)  
Monad m => Extend (TransducerM m i o) 
class ToTransducerM m t where Source
Helps converting pure transducers into monadic ones.
toTransducerM :: t i o r > TransducerM m i o r Source
Monad m => ToTransducerM m Transducer  
(~) (* > *) m m' => ToTransducerM m (TransducerM m') 
Applying transducers
transduce :: ToTransducer t => t i o s > Transduction i o Source
Apply a Transducer
to a Fold
, discarding the return value of the
Transducer
.
>>>
L.fold (transduce (Transducer (\_ i > ((),[i],[])) () (\_ > ('r',[],[]))) L.list) [1..7]
[1,2,3,4,5,6,7]
transduce' :: ToTransducer t => t i o s > Transduction' i o s Source
Generalized version of transduce
that preserves the return value of
the Transducer
.
>>>
L.fold (transduce' (Transducer (\_ i > ((),[i],[])) () (\_ > ('r',[],[]))) L.list) [1..7]
('r',[1,2,3,4,5,6,7])
transduceM :: (Monad m, ToTransducerM m t) => t i o s > TransductionM m i o Source
transduceM' :: (Monad m, ToTransducerM m t) => t i o s > TransductionM' m i o s Source
Like transduce'
, but works on monadic Fold
s.
transduceK :: Monad m => (i > m [o]) > TransductionM m i o Source
Transduce with a Kleisli arrow that returns a list.
Folding over groups
folds :: ToTransducer t => t a b s > Fold b c > Transduction a c Source
Summarizes each of the groups demarcated by the Transducer
using a
Fold
.
The result value of the Transducer
is discarded.
>>>
L.fold (folds (chunksOf 3) L.sum L.list) [1..7]
[6,15,7]
folds' :: ToTransducer t => t a b s > Fold b c > Transduction' a c s Source
Like folds
, but preserves the return value of the Transducer
.
>>>
L.fold (folds' (chunksOf 3) L.sum L.list) [1..7]
((),[6,15,7])
foldsM :: (Applicative m, Monad m, ToTransducerM m t) => t a b s > FoldM m b c > TransductionM m a c Source
Monadic version of folds
.
foldsM' :: (Applicative m, Monad m, ToTransducerM m t) => t a b s > FoldM m b c > TransductionM' m a c s Source
Monadic version of folds'
.
Group operations
newtype ReifiedTransduction a b Source
Helper for storing a Transduction
safely on a container.
:: ToTransducer t  
=> t a b s  
> Infinite (ReifiedTransduction b c)  infinite list of transductions 
> Transduction a c 
Processes each of the groups demarcated by a Transducer
using
a Transduction
taken from an unending supply,
returning a Transduction
what works over the undivided stream of inputs.
The return value of the Transducer
is discarded.
>>>
L.fold (groups (chunksOf 2) (evenly (transduce (surround "<" ">"))) L.list) "aabbccdd"
"<aa><bb><cc><dd>"
>>>
:{
let transducers = flip C.unfold 0 $ \i > (,) (ReifiedTransduction (transduce (surround (show i) []))) (Identity (succ i)) in L.fold (groups (chunksOf 2) transducers L.list) "aabbccdd" :} "0aa1bb2cc3dd"
evenly :: Transduction b c > Infinite (ReifiedTransduction b c) Source
Use the same Transduction
for each group.
:: ToTransducer t  
=> t a b s  
> Transduction b c  head 
> Transduction b c  
> Transduction a c 
Use one transduction to process the first group, and another for the second and all subsequent groups.
type Moore a b = Cofree ((>) a) b Source
Unending machine that gives you a b
whenever you give it an a
.
newtype ReifiedTransduction' a b r Source
Helper for storing a ReifiedTransduction
safely on a container.
:: ToTransducer t  
=> t a b s  
> Fold u v  auxiliary 
> Moore u (ReifiedTransduction' b c u)  a machine that eats 
> Transduction' a c (s, v) 
Generalized version of groups
that preserves the return value of the
Transducer
.
A summary value for each group is also calculated. These values are
aggregated for the whole stream, with the help of an auxiliary Fold
.
>>>
:{
let transductions = evenly' $ \f > transduce (surround "<" ">") (liftA2 (,) L.list f) in L.fold (groups' (chunksOf 2) L.list transductions L.list) "aabbccdd" :} (((),["<aa>","<bb>","<cc>","<dd>"]),"<aa><bb><cc><dd>")
evenly' :: Transduction' b c u > Moore u (ReifiedTransduction' b c u) Source
Use the same Transduction'
for each group.
Ignores the inputs to the Moore machine.
Monadic group operations
newtype ReifiedTransductionM m a b Source
Helper for storing a TransductionM
safely on a container.
:: (Monad m, ToTransducerM m t)  
=> t a b s  
> Infinite (ReifiedTransductionM m b c)  
> TransductionM m a c 
Monadic version of groups
.
evenlyM :: TransductionM m b c > Infinite (ReifiedTransductionM m b c) Source
Monadic version of evenly
.
:: ToTransducerM m t  
=> t a b s  
> TransductionM m b c  head 
> TransductionM m b c  
> TransductionM m a c 
Monadic version of bisect
.
newtype ReifiedTransductionM' m a b r Source
Helper for storing a TransductionM'
safely on a container.
ReifiedTransductionM'  

:: (Monad m, ToTransducerM m t)  
=> t a b s  
> FoldM m u v  
> Moore u (ReifiedTransductionM' m b c u)  a machine that eats 
> TransductionM' m a c (s, v) 
Monadic version of groups'
.
evenlyM' :: TransductionM' m b c u > Moore u (ReifiedTransductionM' m b c u) Source
Monadic version of evenly'
.
Transducers
ignore :: Transducer a b () Source
Ignore all the inputs coming into the fold.
Polymorphic in both inputs and outputs.
surround :: (Traversable p, Traversable s) => p a > s a > Transducer a a () Source
Adds a prefix and a suffix to the stream arriving into a Fold
.
>>>
L.fold (transduce (surround "prefix" "suffix") L.list) "middle"
"prefixmiddlesuffix"
Used as a splitter, it puts the prefix, the original stream and the suffix in separate groups:
>>>
L.fold (groups (surround "prefix" "suffix") (evenly (transduce (surround "[" "]"))) L.list) "middle"
"[prefix][middle][suffix]"
surroundIO :: (Traversable p, Traversable s, Functor m, MonadIO m) => m (p a) > m (s a) > TransducerM m a a () Source
Splitters
chunksOf :: Int > Transducer a a () Source
Splits a stream into chunks of fixed size.
>>>
L.fold (folds (chunksOf 2) L.list L.list) [1..7]
[[1,2],[3,4],[5,6],[7]]
>>>
L.fold (groups (chunksOf 2) (evenly (transduce (surround [] [0]))) L.list) [1..7]
[1,2,0,3,4,0,5,6,0,7,0]
splitAt :: Int > Transducer a a () Source
Splits the stream at a given position.
>>>
L.fold (bisect (splitAt 2) (transduce ignore) id L.list) [1..5]
[3,4,5]
chunkedSplitAt :: StableFactorialMonoid m => Int > Transducer m m () Source
Similar to splitAt
, but works with streams of "chunked" data like
bytestrings, texts, vectors, lists of lists...
>>>
L.fold (bisect (chunkedSplitAt 7) (transduce ignore) id L.list) [[1..5],[6..9]]
[[8,9]]
splitWhen :: (a > Bool) > Transducer a a () Source
>>>
L.fold (bisect (splitWhen (>3)) id (transduce ignore) L.list) [1..5]
[1,2,3]
splitLast :: Transducer a a (Maybe a) Source
Puts the last element of the input stream (if it exists) in a separate group.
>>>
L.fold (bisect splitLast id (transduce ignore) L.list) [1..5]
[1,2,3,4]
:: (LeftGCDMonoid i, StableFactorialMonoid i, Traversable t, Monad m)  
=> t i  
> TransducerM (ExceptT ([i], Maybe i) m) i i () 
Strip a prefix from a stream of "chunked" data, like packed text.
If the prefix doesn't match, fail with the unmatched part of the prefix and the input that caused the error.
>>>
runExceptT $ L.foldM (transduceM (chunkedStripPrefix [[1..2],[3..4]]) (L.generalize L.list)) [[1..5],[6..9]]
Right [[5],[6,7,8,9]]
>>>
runExceptT $ L.foldM (transduceM (chunkedStripPrefix [[1..2],[3,77,99]]) (L.generalize L.list)) [[1..5],[6..9]]
Left ([[77,99]],Just [4,5])
Transducer utilities
foldify :: Transducer i o s > Fold i s Source
Transforms a Transducer
into a Fold
by forgetting about the data sent
downstream.
condense :: Fold a r > Transducer a r r Source
Transforms a Fold
into a Transducer
that sends the return value of the
Fold
downstream when upstream closes.
condenseM :: Applicative m => FoldM m a r > TransducerM m a r r Source
Monadic version of condense
.
hoistTransducer :: Monad m => (forall a. m a > n a) > TransducerM m i o s > TransducerM n i o s Source
Changes the base monad used by a TransducerM
.
Fold utilities
quiesceWith :: (Functor m, Monad m) => FoldM m a v > FoldM (ExceptT e m) a r > FoldM m a (Either (e, v) r) Source
Generalized version of quiesce
to turn a fallible FoldM
into another
that starts a "fallback fold" when it encounters an error.
"Start folding this way, if you encounter an error, start folding this other way".
>>>
L.foldM (quiesceWith (L.generalize L.length) (FoldM (\_ _> throwE ()) (return ()) (\_ > throwE ()))) [1..7]
Left ((),7)
hoistFold :: Monad m => (forall a. m a > n a) > FoldM m i r > FoldM n i r Source
Changes the base monad used by a FoldM
.
Reexports
module Data.Functor.Extend
module Control.Foldl
module Control.Comonad.Cofree