The Combinators module defines combinators applicable to Transducer
and Splitter
components defined in the
ComponentTypes module.
- (->>) :: forall x y m r. (Monad m, Typeable x, Typeable y) => Transducer m x y -> Consumer m y r -> Consumer m x r
- (<<-) :: forall x y m r c c1. (Monad m, Typeable x, Typeable y) => Transducer m x y -> Producer m x r -> Producer m y r
- (>->) :: forall m x y z. Monad m => Transducer m x y -> Transducer m y z -> Transducer m x z
- join :: (Monad m, Typeable x) => Transducer m x y -> Transducer m x y -> Transducer m x y
- snot :: (Monad m, Typeable x) => Splitter m x -> Splitter m x
- (>&) :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x
- (>|) :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x
- (&&) :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x
- (||) :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x
- ifs :: (Monad m, Typeable x) => Splitter m x -> Transducer m x y -> Transducer m x y -> Transducer m x y
- wherever :: (Monad m, Typeable x) => Transducer m x x -> Splitter m x -> Transducer m x x
- unless :: (Monad m, Typeable x) => Transducer m x x -> Splitter m x -> Transducer m x x
- select :: (Monad m, Typeable x) => Splitter m x -> Transducer m x x
- while :: (Monad m, Typeable x) => Transducer m x x -> Splitter m x -> Transducer m x x
- nestedIn :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x
- foreach :: (Monad m, Typeable x, Typeable y) => Splitter m x -> Transducer m x y -> Transducer m x y -> Transducer m x y
- having :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x
- havingOnly :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x
- followedBy :: forall m x. (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x
- even :: (Monad m, Typeable x) => Splitter m x -> Splitter m x
- first :: (Monad m, Typeable x) => Splitter m x -> Splitter m x
- uptoFirst :: (Monad m, Typeable x) => Splitter m x -> Splitter m x
- prefix :: (Monad m, Typeable x) => Splitter m x -> Splitter m x
- last :: (Monad m, Typeable x) => Splitter m x -> Splitter m x
- lastAndAfter :: (Monad m, Typeable x) => Splitter m x -> Splitter m x
- suffix :: (Monad m, Typeable x) => Splitter m x -> Splitter m x
- between :: forall m x. (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x
- (...) :: forall m x. (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x
Consumer and producer combinators
(->>) :: forall x y m r. (Monad m, Typeable x, Typeable y) => Transducer m x y -> Consumer m y r -> Consumer m x rSource
The result of combinator ->>
is a consumer that acts as a composition of the given transducer and consumer
arguments.
(<<-) :: forall x y m r c c1. (Monad m, Typeable x, Typeable y) => Transducer m x y -> Producer m x r -> Producer m y rSource
The result of combinator <<-
is a producer that acts as a composition of the given transducer and producer
arguments.
Transducer combinators
(>->) :: forall m x y z. Monad m => Transducer m x y -> Transducer m y z -> Transducer m x zSource
The >->
combinator composes its argument transducers. The resulting composition t1 >-> t2 passes its input through the
first transducer t1, the output of t1 is passed to the other transducer t2, and its output becomes the output of the
composition.
join :: (Monad m, Typeable x) => Transducer m x y -> Transducer m x y -> Transducer m x ySource
The join
combinator arranges the two transducer arguments in parallel. The input of the resulting transducer is replicated
to both component transducers in parallel, and the output of the resulting transducer is a concatenation of the two component
transducers' outputs.
Pseudo-logic splitter combinators
Combinators >&
and >|
are only pseudo-logic. While the laws of double negation and De Morgan's laws hold,
>&
and >|
are in general not commutative, associative, nor idempotent. In the special case when all argument
splitters are stateless, such as those produced by Components.liftStatelessSplitter
, these combinators do satisfy
all laws of Boolean algebra.
snot :: (Monad m, Typeable x) => Splitter m x -> Splitter m xSource
The snot
(streaming not) combinator simply reverses the outputs of the argument splitter.
In other words, data that the argument splitter sends to its true sink goes to the false sink of the result, and vice versa.
(>&) :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m xSource
The >&
combinator sends the true sink output of its left operand to the input of its right operand for further
splitting. Both operands' false sinks are connected to the false sink of the combined splitter, but any input
value to reach the true sink of the combined component data must be deemed true by both splitters.
(>|) :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m xSource
A >|
combinator's input value can reach its false sink only by going through both argument splitters' false
sinks.
Zipping logic combinators
The &&
and ||
combinators run the argument splitters in parallel and combine their logical outputs using
the corresponding logical operation on each output pair, in a manner similar to zipWith
.
(&&) :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m xSource
Combinator &&
is a pairwise logical conjunction of two splitters run in parallel on the same input.
(||) :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m xSource
Combinator ||
is a pairwise logical disjunction of two splitters run in parallel on the same input.
Flow-control combinators
The following combinators resemble the common flow-control programming language constructs. Combinators
wherever
, unless
, and select
are just the special cases of the combinator ifs
.
ifs :: (Monad m, Typeable x) => Splitter m x -> Transducer m x y -> Transducer m x y -> Transducer m x ySource
The result of the combinator ifs
is a transducer that applies one argument transducer to one portion of
the input and the other transducer to the other portion of input, depending on where the splitter argument routes the data.
wherever :: (Monad m, Typeable x) => Transducer m x x -> Splitter m x -> Transducer m x xSource
unless :: (Monad m, Typeable x) => Transducer m x x -> Splitter m x -> Transducer m x xSource
Recursive
while :: (Monad m, Typeable x) => Transducer m x x -> Splitter m x -> Transducer m x xSource
The recursive combinator while
feeds the true sink of the argument splitter back to itself, modified by the
argument transducer. Data fed to the splitter's false sink is passed on unmodified.
nestedIn :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m xSource
The recursive combinator nestedIn
combines two splitters into a mutually recursive loop acting as a single splitter.
The true sink of one of the argument splitters and false sink of the other become the true and false sinks of the loop.
The other two sinks are bound to the other splitter's source.
The use of nestedIn
makes sense only on hierarchically structured streams. If we gave it some input containing
a flat sequence of values, and assuming both component splitters are deterministic and stateless,
a value would either not loop at all or it would loop forever.
Section-based combinators
All combinators in this section use their Splitter
argument to determine the
structure of the input. Every contiguous portion of the input that gets passed to one or the other sink of the
splitter is treated as one section in the logical structure of the input stream. What is done with the section
depends on the combinator, but the sections, and therefore the logical structure of the input stream, are
determined by the argument splitter alone.
foreach :: (Monad m, Typeable x, Typeable y) => Splitter m x -> Transducer m x y -> Transducer m x y -> Transducer m x ySource
The foreach
combinator is similar to the combinator ifs
in that it combines a splitter and two transducers into
another transducer. However, in this case the transducers are re-instantiated for each consecutive portion of the
input as the splitter chunks it up. Each contiguous portion of the input that the splitter sends to one of its two
sinks gets transducered through the appropriate argument transducer as that transducer's whole input. As soon as the
contiguous portion is finished, the transducer gets terminated.
having :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m xSource
The having
combinator combines two pure splitters into a pure splitter. One splitter is used to chunk the input
into contiguous portions. Its false sink is routed directly to the false sink of the combined splitter. The
second splitter is instantiated and run on each portion of the input that goes to first splitter's true sink. If
the second splitter sends any output at all to its true sink, the whole input portion is passed on to the true
sink of the combined splitter, otherwise it goes to its false sink.
havingOnly :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m xSource
The havingOnly
combinator is analogous to the having
combinator, but it succeeds and passes each chunk of the
input to its true sink only if the second splitter sends no part of it to its false sink.
followedBy :: forall m x. (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m xSource
Combinator followedBy
treats its argument Splitter
s as patterns components and returns a Splitter
that
matches their concatenation. A section of input is considered true by the result iff its prefix is considered
true by argument s1 and the rest of the section is considered true by s2. The splitter s2 is started anew
after every section split to true sink by s1.
first and its variants
first :: (Monad m, Typeable x) => Splitter m x -> Splitter m xSource
The result of combinator first
behaves the same as the argument splitter up to and including the first portion of
the input which goes into the argument's true sink. All input following the first true portion goes into the
false sink.
uptoFirst :: (Monad m, Typeable x) => Splitter m x -> Splitter m xSource
The result of combinator uptoFirst
takes all input up to and including the first portion of the input which goes
into the argument's true sink and feeds it to the result splitter's true sink. All the rest of the input goes
into the false sink. The only difference between last
and lastAndAfter
combinators is in where they direct the
false portion of the input preceding the first true part.
prefix :: (Monad m, Typeable x) => Splitter m x -> Splitter m xSource
The prefix
combinator feeds its true sink only the prefix of the input that its argument feeds to its true sink.
All the rest of the input is dumped into the false sink of the result.
last and its variants
last :: (Monad m, Typeable x) => Splitter m x -> Splitter m xSource
The result of the combinator last
is a splitter which directs all input to its false sink, up to the last
portion of the input which goes to its argument's true sink. That portion of the input is the only one that goes to
the resulting component's true sink. The splitter returned by the combinator last
has to buffer the previous two
portions of its input, because it cannot know if a true portion of the input is the last one until it sees the end of
the input or another portion succeeding the previous one.
lastAndAfter :: (Monad m, Typeable x) => Splitter m x -> Splitter m xSource
The result of the combinator lastAndAfter
is a splitter which directs all input to its false sink, up to the
last portion of the input which goes to its argument's true sink. That portion and the remainder of the input is fed
to the resulting component's true sink. The difference between last
and lastAndAfter
combinators is where they
feed the false portion of the input, if any, remaining after the last true part.
suffix :: (Monad m, Typeable x) => Splitter m x -> Splitter m xSource
The suffix
combinator feeds its true sink only the suffix of the input that its argument feeds to its true sink.
All the rest of the input is dumped into the false sink of the result.
input ranges
between :: forall m x. (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m xSource
Combinator between
passes to its true sink all input that follows a section considered true by its first
argument splitter but not a section considered true by its second argument. The section delimiter pairs can nest to
arbitrary depth.