{- 
    Copyright 2008-2013 Mario Blazevic

    This file is part of the Streaming Component Combinators (SCC) project.

    The SCC project is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
    License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
    version.

    SCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along with SCC.  If not, see
    <http://www.gnu.org/licenses/>.
-}

{-# LANGUAGE RankNTypes, KindSignatures, EmptyDataDecls,
             MultiParamTypeClasses, FlexibleContexts, FlexibleInstances, FunctionalDependencies, TypeFamilies #-}
{-# OPTIONS_HADDOCK prune #-}

-- | This module exports the entire SCC library except for low-level modules "Control.Concurrent.SCC.Streams" and
-- "Control.Concurrent.SCC.Types". The exported combinators can be configured to run their components sequentially or in
-- parallel depending on the available resources.

module Control.Concurrent.SCC.Configurable 
       (
          module Control.Concurrent.SCC.Configurable,
          module Control.Concurrent.Configuration,
          XML.XMLToken(..), XML.expandXMLEntity
       )
where

import Prelude hiding (appendFile, even, id, join, last, sequence, (||), (&&))
import qualified Control.Category
import Data.Text (Text)
import Data.Monoid (Monoid, Sum)
import System.IO (Handle)

import Control.Monad.Coroutine
import Control.Monad.Parallel (MonadParallel(..))
import Data.Monoid.Null (MonoidNull)
import Data.Monoid.Factorial (FactorialMonoid)
import Data.Monoid.Cancellative (LeftCancellativeMonoid)

import Control.Concurrent.SCC.Streams
import Control.Concurrent.SCC.Types
import Control.Concurrent.SCC.Coercions (Coercible)
import qualified Control.Concurrent.SCC.Coercions as Coercion
import qualified Control.Concurrent.SCC.Combinators as Combinator
import qualified Control.Concurrent.SCC.Primitives as Primitive
import qualified Control.Concurrent.SCC.XML as XML
import Control.Concurrent.SCC.Primitives (OccurenceTag)
import Control.Concurrent.SCC.XML (XMLToken)
import Control.Concurrent.Configuration (Component, atomic)
import qualified Control.Concurrent.Configuration as Configuration

-- * Configurable component types

-- | A component that performs a computation with no inputs nor outputs is a 'PerformerComponent'.
type PerformerComponent m r = Component (Performer m r)

-- | A component that consumes values from a 'Source' is called 'ConsumerComponent'.
type ConsumerComponent m x r = Component (Consumer m x r)

-- | A component that produces values and puts them into a 'Sink' is called 'ProducerComponent'.
type ProducerComponent m x r = Component (Producer m x r)

-- | The 'TransducerComponent' type represents computations that transform a data stream.
type TransducerComponent m x y = Component (Transducer m x y)

type ParserComponent m x y = Component (Parser m x y)

-- | The 'SplitterComponent' type represents computations that distribute data acording to some criteria.  A splitter
-- should distribute only the original input data, and feed it into the sinks in the same order it has been read from
-- the source. If the two 'Sink c x' arguments of a splitter are the same, the splitter must act as an identity
-- transform.
type SplitterComponent m x = Component (Splitter m x)

-- | The constant cost of each I/O-performing component.
ioCost :: Int
ioCost :: Int
ioCost = Int
5

-- * Coercible class

-- | A 'TransducerComponent' that converts a stream of one type to another.
coerce :: (Monad m, Coercible x y) => TransducerComponent m x y
coerce :: forall (m :: * -> *) x y.
(Monad m, Coercible x y) =>
TransducerComponent m x y
coerce = String -> Int -> Transducer m x y -> Component (Transducer m x y)
forall c. String -> Int -> c -> Component c
atomic String
"coerce" Int
1 Transducer m x y
forall x y (m :: * -> *).
(Coercible x y, Monad m) =>
Transducer m x y
forall (m :: * -> *). Monad m => Transducer m x y
Coercion.coerce

-- | Adjusts the argument consumer to consume the stream of a data type coercible to the type it was meant to consume.
adaptConsumer :: (Monad m, Monoid x, Monoid y, Coercible x y) => ConsumerComponent m y r -> ConsumerComponent m x r
adaptConsumer :: forall (m :: * -> *) x y r.
(Monad m, Monoid x, Monoid y, Coercible x y) =>
ConsumerComponent m y r -> ConsumerComponent m x r
adaptConsumer = Int
-> String
-> (Consumer m y r -> Consumer m x r)
-> Component (Consumer m y r)
-> Component (Consumer m x r)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
1 String
"adaptConsumer" Consumer m y r -> Consumer m x r
forall x y (m :: * -> *) r.
(Coercible x y, Monad m, Monoid x, Monoid y) =>
Consumer m y r -> Consumer m x r
forall (m :: * -> *) r.
(Monad m, Monoid x, Monoid y) =>
Consumer m y r -> Consumer m x r
Coercion.adaptConsumer

-- | Adjusts the argument producer to produce the stream of a data type coercible from the type it was meant to produce.
adaptProducer :: (Monad m, Monoid x, Monoid y, Coercible x y) => ProducerComponent m x r -> ProducerComponent m y r
adaptProducer :: forall (m :: * -> *) x y r.
(Monad m, Monoid x, Monoid y, Coercible x y) =>
ProducerComponent m x r -> ProducerComponent m y r
adaptProducer = Int
-> String
-> (Producer m x r -> Producer m y r)
-> Component (Producer m x r)
-> Component (Producer m y r)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
1 String
"adaptProducer" Producer m x r -> Producer m y r
forall x y (m :: * -> *) r.
(Coercible x y, Monad m, Monoid x, Monoid y) =>
Producer m x r -> Producer m y r
forall (m :: * -> *) r.
(Monad m, Monoid x, Monoid y) =>
Producer m x r -> Producer m y r
Coercion.adaptProducer

-- * Splitter isomorphism

-- | Adjusts the argument splitter to split the stream of a data type isomorphic to the type it was meant to split.
adaptSplitter :: (Monad m, Monoid x, Monoid y, Coercible x y, Coercible y x) => 
                 SplitterComponent m x -> SplitterComponent m y
adaptSplitter :: forall (m :: * -> *) x y.
(Monad m, Monoid x, Monoid y, Coercible x y, Coercible y x) =>
SplitterComponent m x -> SplitterComponent m y
adaptSplitter = Int
-> String
-> (Splitter m x -> Splitter m y)
-> Component (Splitter m x)
-> Component (Splitter m y)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
1 String
"adaptSplitter" Splitter m x -> Splitter m y
forall (m :: * -> *) x y b.
(Monad m, Monoid x, Monoid y, Coercible x y, Coercible y x) =>
Splitter m x -> Splitter m y
Coercion.adaptSplitter

-- * I/O components
-- ** I/O producers

-- | ProducerComponent 'fromStdIn' feeds the given sink from the standard input.
fromStdIn :: ProducerComponent IO Text ()
fromStdIn :: ProducerComponent IO Text ()
fromStdIn = String
-> Int -> Producer IO Text () -> ProducerComponent IO Text ()
forall c. String -> Int -> c -> Component c
atomic String
"fromStdIn" Int
ioCost Producer IO Text ()
Primitive.fromStdIn

-- | ProducerComponent 'fromFile' opens the named file and feeds the given sink from its contents.
fromFile :: String -> ProducerComponent IO Text ()
fromFile :: String -> ProducerComponent IO Text ()
fromFile String
path = String
-> Int -> Producer IO Text () -> ProducerComponent IO Text ()
forall c. String -> Int -> c -> Component c
atomic String
"fromFile" Int
ioCost (String -> Producer IO Text ()
Primitive.fromFile String
path)

-- | ProducerComponent 'fromHandle' feeds the given sink from the open file /handle/.
fromHandle :: Handle -> ProducerComponent IO Text ()
fromHandle :: Handle -> ProducerComponent IO Text ()
fromHandle Handle
handle = String
-> Int -> Producer IO Text () -> ProducerComponent IO Text ()
forall c. String -> Int -> c -> Component c
atomic String
"fromHandle" Int
ioCost (Handle -> Producer IO Text ()
Primitive.fromHandle Handle
handle)

-- ** I/O consumers

-- | ConsumerComponent 'toStdOut' copies the given source into the standard output.
toStdOut :: ConsumerComponent IO Text ()
toStdOut :: ConsumerComponent IO Text ()
toStdOut = String
-> Int -> Consumer IO Text () -> ConsumerComponent IO Text ()
forall c. String -> Int -> c -> Component c
atomic String
"toStdOut" Int
ioCost Consumer IO Text ()
Primitive.toStdOut

-- | ConsumerComponent 'toFile' opens the named file and copies the given source into it.
toFile :: String -> ConsumerComponent IO Text ()
toFile :: String -> ConsumerComponent IO Text ()
toFile String
path = String
-> Int -> Consumer IO Text () -> ConsumerComponent IO Text ()
forall c. String -> Int -> c -> Component c
atomic String
"toFile" Int
ioCost (String -> Consumer IO Text ()
Primitive.toFile String
path)

-- | ConsumerComponent 'appendFile' opens the name file and appends the given source to it.
appendFile :: String -> ConsumerComponent IO Text ()
appendFile :: String -> ConsumerComponent IO Text ()
appendFile String
path = String
-> Int -> Consumer IO Text () -> ConsumerComponent IO Text ()
forall c. String -> Int -> c -> Component c
atomic String
"appendFile" Int
ioCost (String -> Consumer IO Text ()
Primitive.appendFile String
path)

-- | ConsumerComponent 'toHandle' copies the given source into the open file /handle/.
toHandle :: Handle -> ConsumerComponent IO Text ()
toHandle :: Handle -> ConsumerComponent IO Text ()
toHandle Handle
handle = String
-> Int -> Consumer IO Text () -> ConsumerComponent IO Text ()
forall c. String -> Int -> c -> Component c
atomic String
"toHandle" Int
ioCost (Handle -> Consumer IO Text ()
Primitive.toHandle Handle
handle)

-- * Generic components

-- | 'produceFrom' produces the contents of the given argument.
produceFrom :: (Monad m, MonoidNull x) => x -> ProducerComponent m x ()
produceFrom :: forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
x -> ProducerComponent m x ()
produceFrom x
l = String -> Int -> Producer m x () -> Component (Producer m x ())
forall c. String -> Int -> c -> Component c
atomic String
"produceFrom" Int
1 (x -> Producer m x ()
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
x -> Producer m x ()
Primitive.produceFrom x
l)
   
-- ** Generic consumers

-- | ConsumerComponent 'consumeInto' collects the given source into the return value.
consumeInto :: (Monad m, Monoid x) => ConsumerComponent m x x
consumeInto :: forall (m :: * -> *) x.
(Monad m, Monoid x) =>
ConsumerComponent m x x
consumeInto = String -> Int -> Consumer m x x -> Component (Consumer m x x)
forall c. String -> Int -> c -> Component c
atomic String
"consumeInto" Int
1 Consumer m x x
forall (m :: * -> *) x. (Monad m, Monoid x) => Consumer m x x
Primitive.consumeInto

-- | The 'suppress' consumer suppresses all input it receives. It is equivalent to 'substitute' []
suppress :: Monad m => ConsumerComponent m x ()
suppress :: forall (m :: * -> *) x. Monad m => ConsumerComponent m x ()
suppress = String -> Int -> Consumer m x () -> Component (Consumer m x ())
forall c. String -> Int -> c -> Component c
atomic String
"suppress" Int
1 Consumer m x ()
forall (m :: * -> *) x. Monad m => Consumer m x ()
Primitive.suppress

-- | The 'erroneous' consumer reports an error if any input reaches it.
erroneous :: (Monad m, MonoidNull x) => String -> ConsumerComponent m x ()
erroneous :: forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
String -> ConsumerComponent m x ()
erroneous String
message = String -> Int -> Consumer m x () -> Component (Consumer m x ())
forall c. String -> Int -> c -> Component c
atomic String
"erroneous" Int
0 (String -> Consumer m x ()
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
String -> Consumer m x ()
Primitive.erroneous String
message)

-- ** Generic transducers

-- | TransducerComponent 'id' passes its input through unmodified.
id :: (Monad m, Monoid x) => TransducerComponent m x x
id :: forall (m :: * -> *) x.
(Monad m, Monoid x) =>
TransducerComponent m x x
id = String -> Int -> Transducer m x x -> Component (Transducer m x x)
forall c. String -> Int -> c -> Component c
atomic String
"id" Int
1 (Transducer m x x -> Component (Transducer m x x))
-> Transducer m x x -> Component (Transducer m x x)
forall a b. (a -> b) -> a -> b
$ (forall (a1 :: * -> *) (a2 :: * -> *) (d :: * -> *).
 OpenTransducer m a1 a2 d x x ())
-> Transducer m x x
forall (m :: * -> *) x y.
(forall (a1 :: * -> *) (a2 :: * -> *) (d :: * -> *).
 OpenTransducer m a1 a2 d x y ())
-> Transducer m x y
Transducer Source m a1 x -> Sink m a2 x -> Coroutine d m ()
forall (a1 :: * -> *) (a2 :: * -> *) (d :: * -> *).
OpenTransducer m a1 a2 d x x ()
forall (m :: * -> *) (a1 :: * -> *) (a2 :: * -> *) (d :: * -> *) x.
(Monad m, Monoid x, AncestorFunctor a1 d, AncestorFunctor a2 d) =>
Source m a1 x -> Sink m a2 x -> Coroutine d m ()
pour_

-- | TransducerComponent 'unparse' removes all markup from its input and passes the content through.
unparse :: (Monad m, Monoid x) => TransducerComponent m [Markup b x] x
unparse :: forall (m :: * -> *) x b.
(Monad m, Monoid x) =>
TransducerComponent m [Markup b x] x
unparse = String
-> Int
-> Transducer m [Markup b x] x
-> Component (Transducer m [Markup b x] x)
forall c. String -> Int -> c -> Component c
atomic String
"unparse" Int
1 Transducer m [Markup b x] x
forall (m :: * -> *) x b.
(Monad m, Monoid x) =>
Transducer m [Markup b x] x
Primitive.unparse

-- | TransducerComponent 'parse' prepares input content for subsequent parsing.
parse :: (Monad m, Monoid x) => ParserComponent m x y
parse :: forall (m :: * -> *) x y.
(Monad m, Monoid x) =>
ParserComponent m x y
parse = String -> Int -> Parser m x y -> Component (Parser m x y)
forall c. String -> Int -> c -> Component c
atomic String
"parse" Int
1 Parser m x y
forall (m :: * -> *) x y. (Monad m, Monoid x) => Parser m x y
Primitive.parse

-- | The 'lowercase' transforms all uppercase letters in the input to lowercase, leaving the rest unchanged.
lowercase :: Monad m => TransducerComponent m String String
lowercase :: forall (m :: * -> *).
Monad m =>
TransducerComponent m String String
lowercase = String
-> Int
-> Transducer m String String
-> Component (Transducer m String String)
forall c. String -> Int -> c -> Component c
atomic String
"lowercase" Int
1 Transducer m String String
forall (m :: * -> *). Monad m => Transducer m String String
Primitive.lowercase

-- | The 'uppercase' transforms all lowercase letters in the input to uppercase, leaving the rest unchanged.
uppercase :: Monad m => TransducerComponent m String String
uppercase :: forall (m :: * -> *).
Monad m =>
TransducerComponent m String String
uppercase = String
-> Int
-> Transducer m String String
-> Component (Transducer m String String)
forall c. String -> Int -> c -> Component c
atomic String
"uppercase" Int
1 Transducer m String String
forall (m :: * -> *). Monad m => Transducer m String String
Primitive.uppercase

-- | The 'count' transducer counts all its input values and outputs the final tally.
count :: (Monad m, FactorialMonoid x) => TransducerComponent m x [Integer]
count :: forall (m :: * -> *) x.
(Monad m, FactorialMonoid x) =>
TransducerComponent m x [Integer]
count = String
-> Int
-> Transducer m x [Integer]
-> Component (Transducer m x [Integer])
forall c. String -> Int -> c -> Component c
atomic String
"count" Int
1 Transducer m x [Integer]
forall (m :: * -> *) x.
(Monad m, FactorialMonoid x) =>
Transducer m x [Integer]
Primitive.count

-- | Converts each input value @x@ to @show x@.
toString :: (Monad m, Show x) => TransducerComponent m [x] [String]
toString :: forall (m :: * -> *) x.
(Monad m, Show x) =>
TransducerComponent m [x] [String]
toString = String
-> Int
-> Transducer m [x] [String]
-> Component (Transducer m [x] [String])
forall c. String -> Int -> c -> Component c
atomic String
"toString" Int
1 Transducer m [x] [String]
forall (m :: * -> *) x.
(Monad m, Show x) =>
Transducer m [x] [String]
Primitive.toString

-- | Performs the same task as the 'substring' splitter, but instead of splitting it outputs the input as @'Markup' x
-- 'OccurenceTag'@ in order to distinguish overlapping strings.
parseSubstring :: (Monad m, Eq x, LeftCancellativeMonoid x, FactorialMonoid x) => x -> ParserComponent m x OccurenceTag
parseSubstring :: forall (m :: * -> *) x.
(Monad m, Eq x, LeftCancellativeMonoid x, FactorialMonoid x) =>
x -> ParserComponent m x OccurenceTag
parseSubstring x
list = String
-> Int
-> Parser m x OccurenceTag
-> Component (Parser m x OccurenceTag)
forall c. String -> Int -> c -> Component c
atomic String
"parseSubstring" Int
1 (x -> Parser m x OccurenceTag
forall (m :: * -> *) x.
(Monad m, Eq x, LeftReductiveMonoid x, FactorialMonoid x) =>
x -> Parser m x OccurenceTag
Primitive.parseSubstring x
list)

-- *** List stream transducers

-- | TransducerComponent 'group' collects all its input into a single list item.
group :: (Monad m, Monoid x) => TransducerComponent m x [x]
group :: forall (m :: * -> *) x.
(Monad m, Monoid x) =>
TransducerComponent m x [x]
group = String
-> Int -> Transducer m x [x] -> Component (Transducer m x [x])
forall c. String -> Int -> c -> Component c
atomic String
"group" Int
1 Transducer m x [x]
forall (m :: * -> *) x. (Monad m, Monoid x) => Transducer m x [x]
Primitive.group

-- | TransducerComponent 'concatenate' flattens the input stream of lists of values into the output stream of values.
concatenate :: (Monad m, Monoid x) => TransducerComponent m [x] x
concatenate :: forall (m :: * -> *) x.
(Monad m, Monoid x) =>
TransducerComponent m [x] x
concatenate = String
-> Int -> Transducer m [x] x -> Component (Transducer m [x] x)
forall c. String -> Int -> c -> Component c
atomic String
"concatenate" Int
1 Transducer m [x] x
forall (m :: * -> *) x. (Monad m, Monoid x) => Transducer m [x] x
Primitive.concatenate

-- | Same as 'concatenate' except it inserts the given separator list between every two input lists.
concatSeparate :: (Monad m, MonoidNull x) => x -> TransducerComponent m [x] x
concatSeparate :: forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
x -> TransducerComponent m [x] x
concatSeparate x
separator = String
-> Int -> Transducer m [x] x -> Component (Transducer m [x] x)
forall c. String -> Int -> c -> Component c
atomic String
"concatSeparate" Int
1 (x -> Transducer m [x] x
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
x -> Transducer m [x] x
Primitive.concatSeparate x
separator)

-- ** Generic splitters

-- | SplitterComponent 'everything' feeds its entire input into its /true/ sink.
everything :: Monad m => SplitterComponent m x
everything :: forall (m :: * -> *) x. Monad m => SplitterComponent m x
everything = String -> Int -> Splitter m x -> Component (Splitter m x)
forall c. String -> Int -> c -> Component c
atomic String
"everything" Int
1 Splitter m x
forall (m :: * -> *) x. Monad m => Splitter m x
Primitive.everything

-- | SplitterComponent 'nothing' feeds its entire input into its /false/ sink.
nothing :: (Monad m, Monoid x) => SplitterComponent m x
nothing :: forall (m :: * -> *) x.
(Monad m, Monoid x) =>
SplitterComponent m x
nothing = String -> Int -> Splitter m x -> Component (Splitter m x)
forall c. String -> Int -> c -> Component c
atomic String
"nothing" Int
1 Splitter m x
forall (m :: * -> *) x. (Monad m, Monoid x) => Splitter m x
Primitive.nothing

-- | SplitterComponent 'marked' passes all marked-up input sections to its /true/ sink, and all unmarked input to its
-- /false/ sink.
marked :: (Monad m, Eq y) => SplitterComponent m [Markup y x]
marked :: forall (m :: * -> *) y x.
(Monad m, Eq y) =>
SplitterComponent m [Markup y x]
marked = String
-> Int
-> Splitter m [Markup y x]
-> Component (Splitter m [Markup y x])
forall c. String -> Int -> c -> Component c
atomic String
"marked" Int
1 Splitter m [Markup y x]
forall (m :: * -> *) x y.
(Monad m, Eq y) =>
Splitter m [Markup y x]
Primitive.marked

-- | SplitterComponent 'markedContent' passes the content of all marked-up input sections to its /true/ sink, while the
-- outermost tags and all unmarked input go to its /false/ sink.
markedContent :: (Monad m, Eq y) => SplitterComponent m [Markup y x]
markedContent :: forall (m :: * -> *) y x.
(Monad m, Eq y) =>
SplitterComponent m [Markup y x]
markedContent = String
-> Int
-> Splitter m [Markup y x]
-> Component (Splitter m [Markup y x])
forall c. String -> Int -> c -> Component c
atomic String
"markedContent" Int
1 Splitter m [Markup y x]
forall (m :: * -> *) x y.
(Monad m, Eq y) =>
Splitter m [Markup y x]
Primitive.markedContent

-- | SplitterComponent 'markedWith' passes input sections marked-up with the appropriate tag to its /true/ sink, and the
-- rest of the input to its /false/ sink. The argument /select/ determines if the tag is appropriate.
markedWith :: (Monad m, Eq y) => (y -> Bool) -> SplitterComponent m [Markup y x]
markedWith :: forall (m :: * -> *) y x.
(Monad m, Eq y) =>
(y -> Bool) -> SplitterComponent m [Markup y x]
markedWith y -> Bool
selector = String
-> Int
-> Splitter m [Markup y x]
-> Component (Splitter m [Markup y x])
forall c. String -> Int -> c -> Component c
atomic String
"markedWith" Int
1 ((y -> Bool) -> Splitter m [Markup y x]
forall (m :: * -> *) x y.
(Monad m, Eq y) =>
(y -> Bool) -> Splitter m [Markup y x]
Primitive.markedWith y -> Bool
selector)

-- | SplitterComponent 'contentMarkedWith' passes the content of input sections marked-up with the appropriate tag to
-- its /true/ sink, and the rest of the input to its /false/ sink. The argument /select/ determines if the tag is
-- appropriate.
contentMarkedWith :: (Monad m, Eq y) => (y -> Bool) -> SplitterComponent m [Markup y x]
contentMarkedWith :: forall (m :: * -> *) y x.
(Monad m, Eq y) =>
(y -> Bool) -> SplitterComponent m [Markup y x]
contentMarkedWith y -> Bool
selector = String
-> Int
-> Splitter m [Markup y x]
-> Component (Splitter m [Markup y x])
forall c. String -> Int -> c -> Component c
atomic String
"contentMarkedWith" Int
1 ((y -> Bool) -> Splitter m [Markup y x]
forall (m :: * -> *) x y.
(Monad m, Eq y) =>
(y -> Bool) -> Splitter m [Markup y x]
Primitive.contentMarkedWith y -> Bool
selector)

-- | SplitterComponent 'one' feeds all input values to its /true/ sink, treating every value as a separate section.
one :: (Monad m, FactorialMonoid x) => SplitterComponent m x
one :: forall (m :: * -> *) x.
(Monad m, FactorialMonoid x) =>
SplitterComponent m x
one = String -> Int -> Splitter m x -> Component (Splitter m x)
forall c. String -> Int -> c -> Component c
atomic String
"one" Int
1 Splitter m x
forall (m :: * -> *) x.
(Monad m, FactorialMonoid x) =>
Splitter m x
Primitive.one

-- | SplitterComponent 'substring' feeds to its /true/ sink all input parts that match the contents of the given list
-- argument. If two overlapping parts of the input both match the argument, both are sent to /true/ and each is preceded
-- by an empty chunk on /false/.
substring :: (Monad m, Eq x, LeftCancellativeMonoid x, FactorialMonoid x) => x -> SplitterComponent m x
substring :: forall (m :: * -> *) x.
(Monad m, Eq x, LeftCancellativeMonoid x, FactorialMonoid x) =>
x -> SplitterComponent m x
substring x
list = String -> Int -> Splitter m x -> Component (Splitter m x)
forall c. String -> Int -> c -> Component c
atomic String
"substring" Int
1 (x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, Eq x, LeftReductiveMonoid x, FactorialMonoid x) =>
x -> Splitter m x
Primitive.substring x
list)

-- * Character stream components

-- | SplitterComponent 'whitespace' feeds all white-space characters into its /true/ sink, all others into /false/.
whitespace :: Monad m => SplitterComponent m String
whitespace :: forall (m :: * -> *). Monad m => SplitterComponent m String
whitespace = String -> Int -> Splitter m String -> Component (Splitter m String)
forall c. String -> Int -> c -> Component c
atomic String
"whitespace" Int
1 Splitter m String
forall (m :: * -> *). Monad m => Splitter m String
Primitive.whitespace

-- | SplitterComponent 'letters' feeds all alphabetical characters into its /true/ sink, all other characters into
-- | /false/.
letters :: Monad m => SplitterComponent m String
letters :: forall (m :: * -> *). Monad m => SplitterComponent m String
letters = String -> Int -> Splitter m String -> Component (Splitter m String)
forall c. String -> Int -> c -> Component c
atomic String
"letters" Int
1 Splitter m String
forall (m :: * -> *). Monad m => Splitter m String
Primitive.letters

-- | SplitterComponent 'digits' feeds all digits into its /true/ sink, all other characters into /false/.
digits :: Monad m => SplitterComponent m String
digits :: forall (m :: * -> *). Monad m => SplitterComponent m String
digits = String -> Int -> Splitter m String -> Component (Splitter m String)
forall c. String -> Int -> c -> Component c
atomic String
"digits" Int
1 Splitter m String
forall (m :: * -> *). Monad m => Splitter m String
Primitive.digits

-- | SplitterComponent 'nonEmptyLine' feeds line-ends into its /false/ sink, and all other characters into /true/.
nonEmptyLine :: Monad m => SplitterComponent m String
nonEmptyLine :: forall (m :: * -> *). Monad m => SplitterComponent m String
nonEmptyLine = String -> Int -> Splitter m String -> Component (Splitter m String)
forall c. String -> Int -> c -> Component c
atomic String
"nonEmptyLine" Int
1 Splitter m String
forall (m :: * -> *). Monad m => Splitter m String
Primitive.nonEmptyLine

-- | The sectioning splitter 'line' feeds line-ends into its /false/ sink, and line contents into /true/. A single
-- line-end can be formed by any of the character sequences \"\\n\", \"\\r\", \"\\r\\n\", or \"\\n\\r\".
line :: Monad m => SplitterComponent m String
line :: forall (m :: * -> *). Monad m => SplitterComponent m String
line = String -> Int -> Splitter m String -> Component (Splitter m String)
forall c. String -> Int -> c -> Component c
atomic String
"line" Int
1 Splitter m String
forall (m :: * -> *). Monad m => Splitter m String
Primitive.line

-- * Consumer, producer, and transducer combinators

-- | Converts a 'ConsumerComponent' into a 'TransducerComponent' with no output.
consumeBy :: (Monad m) => ConsumerComponent m x r -> TransducerComponent m x y
consumeBy :: forall (m :: * -> *) x r y.
Monad m =>
ConsumerComponent m x r -> TransducerComponent m x y
consumeBy = Int
-> String
-> (Consumer m x r -> Transducer m x y)
-> Component (Consumer m x r)
-> Component (Transducer m x y)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
1 String
"consumeBy" Consumer m x r -> Transducer m x y
forall (m :: * -> *) x y r.
Monad m =>
Consumer m x r -> Transducer m x y
Combinator.consumeBy

-- | Class 'PipeableComponentPair' applies to any two components that can be combined into a third component with the
-- following properties:
--
--    * The input of the result, if any, becomes the input of the first component.
--
--    * The output produced by the first child component is consumed by the second child component.
--
--    * The result output, if any, is the output of the second component.

(>->) :: (MonadParallel m, PipeableComponentPair m w c1 c2 c3) => 
         Component c1 -> Component c2 -> Component c3
>-> :: forall (m :: * -> *) w c1 c2 c3.
(MonadParallel m, PipeableComponentPair m w c1 c2 c3) =>
Component c1 -> Component c2 -> Component c3
(>->) = String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
forall (m :: * -> *) c1 c2 c3.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
liftParallelPair String
">->" PairBinder m -> c1 -> c2 -> c3
forall (m :: * -> *) w c1 c2 c3.
PipeableComponentPair m w c1 c2 c3 =>
PairBinder m -> c1 -> c2 -> c3
compose

class CompatibleSignature c cons (m :: * -> *) input output | c -> cons m

class AnyListOrUnit c

instance AnyListOrUnit [x]
instance AnyListOrUnit ()

instance (AnyListOrUnit x, AnyListOrUnit y) => CompatibleSignature (Performer m r)    (PerformerType r)  m x y
instance AnyListOrUnit y                    => CompatibleSignature (Consumer m x r)   (ConsumerType r)   m [x] y
instance AnyListOrUnit y                    => CompatibleSignature (Producer m x r)   (ProducerType r)   m y [x]
instance                                       CompatibleSignature (Transducer m x y)  TransducerType    m [x] [y]

data PerformerType r
data ConsumerType r
data ProducerType r
data TransducerType

-- | Class 'JoinableComponentPair' applies to any two components that can be combined into a third component with the
-- following properties:
--
--    * if both argument components consume input, the input of the combined component gets distributed to both
--      components in parallel,
--
--    * if both argument components produce output, the output of the combined component is a concatenation of the
--      complete output from the first component followed by the complete output of the second component, and

-- | The 'join' combinator may apply the components in any order.
join :: (MonadParallel m, Combinator.JoinableComponentPair t1 t2 t3 m x y c1 c2 c3) => 
        Component c1 -> Component c2 -> Component c3
join :: forall (m :: * -> *) t1 t2 t3 x y c1 c2 c3.
(MonadParallel m, JoinableComponentPair t1 t2 t3 m x y c1 c2 c3) =>
Component c1 -> Component c2 -> Component c3
join = String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
forall (m :: * -> *) c1 c2 c3.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
liftParallelPair String
"join" PairBinder m -> c1 -> c2 -> c3
forall t1 t2 t3 (m :: * -> *) x y c1 c2 c3.
JoinableComponentPair t1 t2 t3 m x y c1 c2 c3 =>
PairBinder m -> c1 -> c2 -> c3
Combinator.join

-- | The 'sequence' combinator makes sure its first argument has completed before using the second one.
sequence :: Combinator.JoinableComponentPair t1 t2 t3 m x y c1 c2 c3 => Component c1 -> Component c2 -> Component c3
sequence :: forall t1 t2 t3 (m :: * -> *) x y c1 c2 c3.
JoinableComponentPair t1 t2 t3 m x y c1 c2 c3 =>
Component c1 -> Component c2 -> Component c3
sequence = String
-> (c1 -> c2 -> c3) -> Component c1 -> Component c2 -> Component c3
forall c1 c2 c3.
String
-> (c1 -> c2 -> c3) -> Component c1 -> Component c2 -> Component c3
Configuration.liftSequentialPair String
"sequence" c1 -> c2 -> c3
forall t1 t2 t3 (m :: * -> *) x y c1 c2 c3.
JoinableComponentPair t1 t2 t3 m x y c1 c2 c3 =>
c1 -> c2 -> c3
Combinator.sequence

-- | Combinator 'prepend' converts the given producer to transducer that passes all its input through unmodified, except
-- | for prepending the output of the argument producer to it.
-- | 'prepend' /prefix/ = 'join' ('substitute' /prefix/) 'asis'
prepend :: (Monad m) => ProducerComponent m x r -> TransducerComponent m x x
prepend :: forall (m :: * -> *) x r.
Monad m =>
ProducerComponent m x r -> TransducerComponent m x x
prepend = Int
-> String
-> (Producer m x r -> Transducer m x x)
-> Component (Producer m x r)
-> Component (Transducer m x x)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
1 String
"prepend" Producer m x r -> Transducer m x x
forall (m :: * -> *) x r.
Monad m =>
Producer m x r -> Transducer m x x
Combinator.prepend

-- | Combinator 'append' converts the given producer to transducer that passes all its input through unmodified, finally
-- | appending to it the output of the argument producer.
-- | 'append' /suffix/ = 'join' 'asis' ('substitute' /suffix/)
append :: (Monad m) => ProducerComponent m x r -> TransducerComponent m x x
append :: forall (m :: * -> *) x r.
Monad m =>
ProducerComponent m x r -> TransducerComponent m x x
append = Int
-> String
-> (Producer m x r -> Transducer m x x)
-> Component (Producer m x r)
-> Component (Transducer m x x)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
1 String
"append" Producer m x r -> Transducer m x x
forall (m :: * -> *) x r.
Monad m =>
Producer m x r -> Transducer m x x
Combinator.append

-- | The 'substitute' combinator converts its argument producer to a transducer that produces the same output, while
-- | consuming its entire input and ignoring it.
substitute :: (Monad m, Monoid x) => ProducerComponent m y r -> TransducerComponent m x y
substitute :: forall (m :: * -> *) x y r.
(Monad m, Monoid x) =>
ProducerComponent m y r -> TransducerComponent m x y
substitute = Int
-> String
-> (Producer m y r -> Transducer m x y)
-> Component (Producer m y r)
-> Component (Transducer m x y)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
1 String
"substitute" Producer m y r -> Transducer m x y
forall (m :: * -> *) x y r.
(Monad m, Monoid x) =>
Producer m y r -> Transducer m x y
Combinator.substitute

-- * Splitter combinators

-- | 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.
snot :: (Monad m, Monoid x) => SplitterComponent m x -> SplitterComponent m x
snot :: forall (m :: * -> *) x.
(Monad m, Monoid x) =>
SplitterComponent m x -> SplitterComponent m x
snot = Int
-> String
-> (Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
1 String
"not" Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, Monoid x) =>
Splitter m x -> Splitter m x
Combinator.sNot

-- ** Pseudo-logic flow combinators

-- | 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.
(>&) :: (MonadParallel m, Monoid x) => SplitterComponent m x -> SplitterComponent m x -> SplitterComponent m x
>& :: forall (m :: * -> *) x.
(MonadParallel m, Monoid x) =>
SplitterComponent m x
-> SplitterComponent m x -> SplitterComponent m x
(>&) = String
-> (PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall (m :: * -> *) c1 c2 c3.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
liftParallelPair String
">&" PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, Monoid x) =>
PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x
Combinator.sAnd

-- | A '>|' combinator's input value can reach its /false/ sink only by going through both argument splitters' /false/
-- sinks.
(>|) :: (MonadParallel m, Monoid x) => SplitterComponent m x -> SplitterComponent m x -> SplitterComponent m x
>| :: forall (m :: * -> *) x.
(MonadParallel m, Monoid x) =>
SplitterComponent m x
-> SplitterComponent m x -> SplitterComponent m x
(>|) = String
-> (PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall (m :: * -> *) c1 c2 c3.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
liftParallelPair String
">&" PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, Monoid x) =>
PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x
Combinator.sOr

-- ** Zipping logic combinators

-- | Combinator '&&' is a pairwise logical conjunction of two splitters run in parallel on the same input.
(&&) :: (MonadParallel m, FactorialMonoid x) => SplitterComponent m x -> SplitterComponent m x -> SplitterComponent m x
&& :: forall (m :: * -> *) x.
(MonadParallel m, FactorialMonoid x) =>
SplitterComponent m x
-> SplitterComponent m x -> SplitterComponent m x
(&&) = String
-> (PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall (m :: * -> *) c1 c2 c3.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
liftParallelPair String
"&&" PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, FactorialMonoid x) =>
PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x
Combinator.pAnd

-- | Combinator '||' is a pairwise logical disjunction of two splitters run in parallel on the same input.
(||) :: (MonadParallel m, FactorialMonoid x) => SplitterComponent m x -> SplitterComponent m x -> SplitterComponent m x
|| :: forall (m :: * -> *) x.
(MonadParallel m, FactorialMonoid x) =>
SplitterComponent m x
-> SplitterComponent m x -> SplitterComponent m x
(||) = String
-> (PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall (m :: * -> *) c1 c2 c3.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
liftParallelPair String
"||" PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, FactorialMonoid x) =>
PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x
Combinator.pOr

-- * Flow-control combinators

ifs :: (MonadParallel m, Branching c m x ()) => SplitterComponent m x -> Component c -> Component c -> Component c
ifs :: forall (m :: * -> *) c x.
(MonadParallel m, Branching c m x ()) =>
SplitterComponent m x -> Component c -> Component c -> Component c
ifs = String
-> (PairBinder m -> Splitter m x -> c -> c -> c)
-> Component (Splitter m x)
-> Component c
-> Component c
-> Component c
forall (m :: * -> *) c1 c2 c3 c4.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3 -> c4)
-> Component c1
-> Component c2
-> Component c3
-> Component c4
parallelRouterAndBranches String
"ifs" PairBinder m -> Splitter m x -> c -> c -> c
forall c (m :: * -> *) x.
(Monad m, Branching c m x ()) =>
PairBinder m -> Splitter m x -> c -> c -> c
Combinator.ifs

wherever :: (MonadParallel m, Monoid x) =>
            TransducerComponent m x x -> SplitterComponent m x -> TransducerComponent m x x
wherever :: forall (m :: * -> *) x.
(MonadParallel m, Monoid x) =>
TransducerComponent m x x
-> SplitterComponent m x -> TransducerComponent m x x
wherever = String
-> (PairBinder m
    -> Transducer m x x -> Splitter m x -> Transducer m x x)
-> Component (Transducer m x x)
-> Component (Splitter m x)
-> Component (Transducer m x x)
forall (m :: * -> *) c1 c2 c3.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
liftParallelPair String
"wherever" PairBinder m
-> Transducer m x x -> Splitter m x -> Transducer m x x
forall (m :: * -> *) x.
(Monad m, Monoid x) =>
PairBinder m
-> Transducer m x x -> Splitter m x -> Transducer m x x
Combinator.wherever

unless :: (MonadParallel m, Monoid x) =>
          TransducerComponent m x x -> SplitterComponent m x -> TransducerComponent m x x
unless :: forall (m :: * -> *) x.
(MonadParallel m, Monoid x) =>
TransducerComponent m x x
-> SplitterComponent m x -> TransducerComponent m x x
unless = String
-> (PairBinder m
    -> Transducer m x x -> Splitter m x -> Transducer m x x)
-> Component (Transducer m x x)
-> Component (Splitter m x)
-> Component (Transducer m x x)
forall (m :: * -> *) c1 c2 c3.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
liftParallelPair String
"unless" PairBinder m
-> Transducer m x x -> Splitter m x -> Transducer m x x
forall (m :: * -> *) x.
(Monad m, Monoid x) =>
PairBinder m
-> Transducer m x x -> Splitter m x -> Transducer m x x
Combinator.unless

select :: (Monad m, Monoid x) => SplitterComponent m x -> TransducerComponent m x x
select :: forall (m :: * -> *) x.
(Monad m, Monoid x) =>
SplitterComponent m x -> TransducerComponent m x x
select = Int
-> String
-> (Splitter m x -> Transducer m x x)
-> Component (Splitter m x)
-> Component (Transducer m x x)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
1 String
"select" Splitter m x -> Transducer m x x
forall (m :: * -> *) x.
(Monad m, Monoid x) =>
Splitter m x -> Transducer m x x
Combinator.select

-- ** Recursive

-- | 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.
while :: (MonadParallel m, MonoidNull x) =>
         TransducerComponent m x x -> SplitterComponent m x -> TransducerComponent m x x
while :: forall (m :: * -> *) x.
(MonadParallel m, MonoidNull x) =>
TransducerComponent m x x
-> SplitterComponent m x -> TransducerComponent m x x
while TransducerComponent m x x
t SplitterComponent m x
s = String
-> (PairBinder m
    -> (Transducer m x x, Splitter m x)
    -> Transducer m x x
    -> Transducer m x x)
-> Component (Transducer m x x, Splitter m x)
-> TransducerComponent m x x
forall (m :: * -> *) c1 c2.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c2) -> Component c1 -> Component c2
recursiveComponentTree String
"while" (\PairBinder m
binder-> (Transducer m x x
 -> Splitter m x -> Transducer m x x -> Transducer m x x)
-> (Transducer m x x, Splitter m x)
-> Transducer m x x
-> Transducer m x x
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (PairBinder m
-> Transducer m x x
-> Splitter m x
-> Transducer m x x
-> Transducer m x x
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
PairBinder m
-> Transducer m x x
-> Splitter m x
-> Transducer m x x
-> Transducer m x x
Combinator.while (x -> y -> m r) -> m x -> m y -> m r
PairBinder m
binder)) (Component (Transducer m x x, Splitter m x)
 -> TransducerComponent m x x)
-> Component (Transducer m x x, Splitter m x)
-> TransducerComponent m x x
forall a b. (a -> b) -> a -> b
$
            String
-> (Transducer m x x
    -> Splitter m x -> (Transducer m x x, Splitter m x))
-> TransducerComponent m x x
-> SplitterComponent m x
-> Component (Transducer m x x, Splitter m x)
forall c1 c2 c3.
String
-> (c1 -> c2 -> c3) -> Component c1 -> Component c2 -> Component c3
Configuration.liftSequentialPair String
"pair" (,) TransducerComponent m x x
t SplitterComponent m x
s

-- | 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, an input value would either not loop at all or it would
-- loop forever.
nestedIn :: (MonadParallel m, MonoidNull x) => SplitterComponent m x -> SplitterComponent m x -> SplitterComponent m x
nestedIn :: forall (m :: * -> *) x.
(MonadParallel m, MonoidNull x) =>
SplitterComponent m x
-> SplitterComponent m x -> SplitterComponent m x
nestedIn SplitterComponent m x
s1 SplitterComponent m x
s2 = String
-> (PairBinder m
    -> (Splitter m x, Splitter m x) -> Splitter m x -> Splitter m x)
-> Component (Splitter m x, Splitter m x)
-> SplitterComponent m x
forall (m :: * -> *) c1 c2.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c2) -> Component c1 -> Component c2
recursiveComponentTree String
"nestedIn" (\PairBinder m
binder-> (Splitter m x -> Splitter m x -> Splitter m x -> Splitter m x)
-> (Splitter m x, Splitter m x) -> Splitter m x -> Splitter m x
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (PairBinder m
-> Splitter m x -> Splitter m x -> Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
PairBinder m
-> Splitter m x -> Splitter m x -> Splitter m x -> Splitter m x
Combinator.nestedIn (x -> y -> m r) -> m x -> m y -> m r
PairBinder m
binder)) (Component (Splitter m x, Splitter m x) -> SplitterComponent m x)
-> Component (Splitter m x, Splitter m x) -> SplitterComponent m x
forall a b. (a -> b) -> a -> b
$
                 String
-> (Splitter m x -> Splitter m x -> (Splitter m x, Splitter m x))
-> SplitterComponent m x
-> SplitterComponent m x
-> Component (Splitter m x, Splitter m x)
forall c1 c2 c3.
String
-> (c1 -> c2 -> c3) -> Component c1 -> Component c2 -> Component c3
Configuration.liftSequentialPair String
"pair" (,) SplitterComponent m x
s1 SplitterComponent m x
s2

-- * Section-based combinators

-- | 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.
foreach :: (MonadParallel m, MonoidNull x, Branching c m x ()) =>
           SplitterComponent m x -> Component c -> Component c -> Component c
foreach :: forall (m :: * -> *) x c.
(MonadParallel m, MonoidNull x, Branching c m x ()) =>
SplitterComponent m x -> Component c -> Component c -> Component c
foreach = String
-> (PairBinder m -> Splitter m x -> c -> c -> c)
-> Component (Splitter m x)
-> Component c
-> Component c
-> Component c
forall (m :: * -> *) c1 c2 c3 c4.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3 -> c4)
-> Component c1
-> Component c2
-> Component c3
-> Component c4
parallelRouterAndBranches String
"foreach" PairBinder m -> Splitter m x -> c -> c -> c
forall (m :: * -> *) x c.
(Monad m, MonoidNull x, Branching c m x ()) =>
PairBinder m -> Splitter m x -> c -> c -> c
Combinator.foreach

-- | 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.
having :: (MonadParallel m, MonoidNull x, MonoidNull y, Coercible x y) =>
          SplitterComponent m x -> SplitterComponent m y -> SplitterComponent m x
having :: forall (m :: * -> *) x y.
(MonadParallel m, MonoidNull x, MonoidNull y, Coercible x y) =>
SplitterComponent m x
-> SplitterComponent m y -> SplitterComponent m x
having = String
-> (PairBinder m -> Splitter m x -> Splitter m y -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m y)
-> Component (Splitter m x)
forall (m :: * -> *) c1 c2 c3.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
liftParallelPair String
"having" PairBinder m -> Splitter m x -> Splitter m y -> Splitter m x
forall (m :: * -> *) x y.
(Monad m, MonoidNull x, MonoidNull y, Coercible x y) =>
PairBinder m -> Splitter m x -> Splitter m y -> Splitter m x
Combinator.having

-- | 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.
havingOnly :: (MonadParallel m, MonoidNull x, MonoidNull y, Coercible x y) =>
              SplitterComponent m x -> SplitterComponent m y -> SplitterComponent m x
havingOnly :: forall (m :: * -> *) x y.
(MonadParallel m, MonoidNull x, MonoidNull y, Coercible x y) =>
SplitterComponent m x
-> SplitterComponent m y -> SplitterComponent m x
havingOnly = String
-> (PairBinder m -> Splitter m x -> Splitter m y -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m y)
-> Component (Splitter m x)
forall (m :: * -> *) c1 c2 c3.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
liftParallelPair String
"havingOnly" PairBinder m -> Splitter m x -> Splitter m y -> Splitter m x
forall (m :: * -> *) x y.
(Monad m, MonoidNull x, MonoidNull y, Coercible x y) =>
PairBinder m -> Splitter m x -> Splitter m y -> Splitter m x
Combinator.havingOnly

-- | Combinator 'followedBy' treats its argument 'SplitterComponent's as patterns components and returns a
-- 'SplitterComponent' 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/.
followedBy :: (MonadParallel m, FactorialMonoid x) =>
              SplitterComponent m x -> SplitterComponent m x -> SplitterComponent m x
followedBy :: forall (m :: * -> *) x.
(MonadParallel m, FactorialMonoid x) =>
SplitterComponent m x
-> SplitterComponent m x -> SplitterComponent m x
followedBy = String
-> (PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall (m :: * -> *) c1 c2 c3.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
liftParallelPair String
"followedBy" PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, FactorialMonoid x) =>
PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x
Combinator.followedBy

-- | The 'even' combinator takes every input section that its argument /splitter/ deems /true/, and feeds even ones into
-- its /true/ sink. The odd sections and parts of input that are /false/ according to its argument splitter are fed to
-- 'even' splitter's /false/ sink.
even :: (Monad m, MonoidNull x) => SplitterComponent m x -> SplitterComponent m x
even :: forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
SplitterComponent m x -> SplitterComponent m x
even = Int
-> String
-> (Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
2 String
"even" Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
Splitter m x -> Splitter m x
Combinator.even

-- ** first and its variants

-- | 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.
first :: (Monad m, MonoidNull x) => SplitterComponent m x -> SplitterComponent m x
first :: forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
SplitterComponent m x -> SplitterComponent m x
first = Int
-> String
-> (Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
2 String
"first" Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
Splitter m x -> Splitter m x
Combinator.first

-- | 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 'first' and 'uptoFirst' combinators is in where they direct the
-- /false/ portion of the input preceding the first /true/ part.
uptoFirst :: (Monad m, MonoidNull x) => SplitterComponent m x -> SplitterComponent m x
uptoFirst :: forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
SplitterComponent m x -> SplitterComponent m x
uptoFirst = Int
-> String
-> (Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
2 String
"uptoFirst" Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
Splitter m x -> Splitter m x
Combinator.uptoFirst

-- | 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.
prefix :: (Monad m, MonoidNull x) => SplitterComponent m x -> SplitterComponent m x
prefix :: forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
SplitterComponent m x -> SplitterComponent m x
prefix = Int
-> String
-> (Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
2 String
"prefix" Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
Splitter m x -> Splitter m x
Combinator.prefix

-- ** last and its variants

-- | 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.
last :: (Monad m, MonoidNull x) => SplitterComponent m x -> SplitterComponent m x
last :: forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
SplitterComponent m x -> SplitterComponent m x
last = Int
-> String
-> (Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
2 String
"last" Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
Splitter m x -> Splitter m x
Combinator.last

-- | 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.
lastAndAfter :: (Monad m, MonoidNull x) => SplitterComponent m x -> SplitterComponent m x
lastAndAfter :: forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
SplitterComponent m x -> SplitterComponent m x
lastAndAfter = Int
-> String
-> (Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
2 String
"lastAndAfter" Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
Splitter m x -> Splitter m x
Combinator.lastAndAfter

-- | 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.
suffix :: (Monad m, MonoidNull x) => SplitterComponent m x -> SplitterComponent m x
suffix :: forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
SplitterComponent m x -> SplitterComponent m x
suffix = Int
-> String
-> (Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
2 String
"suffix" Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
Splitter m x -> Splitter m x
Combinator.suffix

-- ** positional splitters

-- | SplitterComponent 'startOf' issues an empty /true/ section at the beginning of every section considered /true/ by
-- its argument splitter, otherwise the entire input goes into its /false/ sink.
startOf :: (Monad m, MonoidNull x) => SplitterComponent m x -> SplitterComponent m x
startOf :: forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
SplitterComponent m x -> SplitterComponent m x
startOf = Int
-> String
-> (Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
2 String
"startOf" Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
Splitter m x -> Splitter m x
Combinator.startOf

-- | SplitterComponent 'endOf' issues an empty /true/ section at the end of every section considered /true/ by its
-- argument splitter, otherwise the entire input goes into its /false/ sink.
endOf :: (Monad m, MonoidNull x) => SplitterComponent m x -> SplitterComponent m x
endOf :: forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
SplitterComponent m x -> SplitterComponent m x
endOf = Int
-> String
-> (Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
2 String
"endOf" Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
Splitter m x -> Splitter m x
Combinator.endOf

-- | Combinator '...' tracks the running balance of difference between the number of preceding starts of sections
-- considered /true/ according to its first argument and the ones according to its second argument. The combinator
-- passes to /true/ all input values for which the difference balance is positive. This combinator is typically used
-- with 'startOf' and 'endOf' in order to count entire input sections and ignore their lengths.
(...) :: (MonadParallel m, FactorialMonoid x) => SplitterComponent m x -> SplitterComponent m x -> SplitterComponent m x
... :: forall (m :: * -> *) x.
(MonadParallel m, FactorialMonoid x) =>
SplitterComponent m x
-> SplitterComponent m x -> SplitterComponent m x
(...) = String
-> (PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
-> Component (Splitter m x)
forall (m :: * -> *) c1 c2 c3.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
liftParallelPair String
"..." PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x
forall (m :: * -> *) x.
(Monad m, FactorialMonoid x) =>
PairBinder m -> Splitter m x -> Splitter m x -> Splitter m x
Combinator.between

-- * Parser support

-- | Converts a splitter into a parser.
parseRegions :: (Monad m, MonoidNull x) => SplitterComponent m x -> ParserComponent m x ()
parseRegions :: forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
SplitterComponent m x -> ParserComponent m x ()
parseRegions = Int
-> String
-> (Splitter m x -> Parser m x ())
-> Component (Splitter m x)
-> Component (Parser m x ())
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
1 String
"parseRegions" Splitter m x -> Parser m x ()
forall (m :: * -> *) x.
(Monad m, MonoidNull x) =>
Splitter m x -> Parser m x ()
Combinator.parseRegions

-- * Parsing XML

-- | This splitter splits XML markup from data content. It is used by 'parseXMLTokens'.
xmlTokens :: Monad m => SplitterComponent m Text
xmlTokens :: forall (m :: * -> *). Monad m => SplitterComponent m Text
xmlTokens = String -> Int -> Splitter m Text -> Component (Splitter m Text)
forall c. String -> Int -> c -> Component c
atomic String
"XML.tokens" Int
1 Splitter m Text
forall (m :: * -> *). Monad m => Splitter m Text
XML.xmlTokens

-- | The XML token parser. This parser converts plain text to parsed text, which is a precondition for using the
-- remaining XML components.
xmlParseTokens :: MonadParallel m => TransducerComponent m Text [Markup XMLToken Text]
xmlParseTokens :: forall (m :: * -> *).
MonadParallel m =>
TransducerComponent m Text [Markup XMLToken Text]
xmlParseTokens = String
-> Int
-> Transducer m Text [Markup XMLToken Text]
-> Component (Transducer m Text [Markup XMLToken Text])
forall c. String -> Int -> c -> Component c
atomic String
"XML.parseTokens" Int
1 Transducer m Text [Markup XMLToken Text]
forall (m :: * -> *).
Monad m =>
Transducer m Text [Markup XMLToken Text]
XML.parseXMLTokens

-- * XML splitters

-- | Splits all top-level elements with all their content to /true/, all other input to /false/.
xmlElement :: Monad m => SplitterComponent m [Markup XMLToken Text]
xmlElement :: forall (m :: * -> *).
Monad m =>
SplitterComponent m [Markup XMLToken Text]
xmlElement = String
-> Int
-> Splitter m [Markup XMLToken Text]
-> Component (Splitter m [Markup XMLToken Text])
forall c. String -> Int -> c -> Component c
atomic String
"XML.element" Int
1 Splitter m [Markup XMLToken Text]
forall (m :: * -> *). Monad m => Splitter m [Markup XMLToken Text]
XML.xmlElement

-- | Splits the content of all top-level elements to /true/, their tags and intervening input to /false/.
xmlElementContent :: Monad m => SplitterComponent m [Markup XMLToken Text]
xmlElementContent :: forall (m :: * -> *).
Monad m =>
SplitterComponent m [Markup XMLToken Text]
xmlElementContent = String
-> Int
-> Splitter m [Markup XMLToken Text]
-> Component (Splitter m [Markup XMLToken Text])
forall c. String -> Int -> c -> Component c
atomic String
"XML.elementContent" Int
1 Splitter m [Markup XMLToken Text]
forall (m :: * -> *). Monad m => Splitter m [Markup XMLToken Text]
XML.xmlElementContent

-- | Similiar to @('Control.Concurrent.SCC.Combinators.having' 'element')@, except it runs the argument splitter
-- only on each element's start tag, not on the entire element with its content.
xmlElementHavingTagWith :: MonadParallel m =>
                       SplitterComponent m [Markup XMLToken Text] -> SplitterComponent m [Markup XMLToken Text]
xmlElementHavingTagWith :: forall (m :: * -> *).
MonadParallel m =>
SplitterComponent m [Markup XMLToken Text]
-> SplitterComponent m [Markup XMLToken Text]
xmlElementHavingTagWith = Int
-> String
-> (Splitter m [Markup XMLToken Text]
    -> Splitter m [Markup XMLToken Text])
-> Component (Splitter m [Markup XMLToken Text])
-> Component (Splitter m [Markup XMLToken Text])
forall c1 c2.
Int -> String -> (c1 -> c2) -> Component c1 -> Component c2
Configuration.lift Int
2 String
"XML.elementHavingTag" Splitter m [Markup XMLToken Text]
-> Splitter m [Markup XMLToken Text]
forall (m :: * -> *) b.
Monad m =>
Splitter m [Markup XMLToken Text]
-> Splitter m [Markup XMLToken Text]
XML.xmlElementHavingTagWith

-- | Splits every attribute specification to /true/, everything else to /false/.
xmlAttribute :: Monad m => SplitterComponent m [Markup XMLToken Text]
xmlAttribute :: forall (m :: * -> *).
Monad m =>
SplitterComponent m [Markup XMLToken Text]
xmlAttribute = String
-> Int
-> Splitter m [Markup XMLToken Text]
-> Component (Splitter m [Markup XMLToken Text])
forall c. String -> Int -> c -> Component c
atomic String
"XML.attribute" Int
1 Splitter m [Markup XMLToken Text]
forall (m :: * -> *). Monad m => Splitter m [Markup XMLToken Text]
XML.xmlAttribute

-- | Splits every element name, including the names of nested elements and names in end tags, to /true/, all the rest of
-- input to /false/.
xmlElementName :: Monad m => SplitterComponent m [Markup XMLToken Text]
xmlElementName :: forall (m :: * -> *).
Monad m =>
SplitterComponent m [Markup XMLToken Text]
xmlElementName = String
-> Int
-> Splitter m [Markup XMLToken Text]
-> Component (Splitter m [Markup XMLToken Text])
forall c. String -> Int -> c -> Component c
atomic String
"XML.elementName" Int
1 Splitter m [Markup XMLToken Text]
forall (m :: * -> *). Monad m => Splitter m [Markup XMLToken Text]
XML.xmlElementName

-- | Splits every attribute name to /true/, all the rest of input to /false/.
xmlAttributeName :: Monad m => SplitterComponent m [Markup XMLToken Text]
xmlAttributeName :: forall (m :: * -> *).
Monad m =>
SplitterComponent m [Markup XMLToken Text]
xmlAttributeName = String
-> Int
-> Splitter m [Markup XMLToken Text]
-> Component (Splitter m [Markup XMLToken Text])
forall c. String -> Int -> c -> Component c
atomic String
"XML.attributeName" Int
1 Splitter m [Markup XMLToken Text]
forall (m :: * -> *). Monad m => Splitter m [Markup XMLToken Text]
XML.xmlAttributeName

-- | Splits every attribute value, excluding the quote delimiters, to /true/, all the rest of input to /false/.
xmlAttributeValue :: Monad m => SplitterComponent m [Markup XMLToken Text]
xmlAttributeValue :: forall (m :: * -> *).
Monad m =>
SplitterComponent m [Markup XMLToken Text]
xmlAttributeValue = String
-> Int
-> Splitter m [Markup XMLToken Text]
-> Component (Splitter m [Markup XMLToken Text])
forall c. String -> Int -> c -> Component c
atomic String
"XML.attributeValue" Int
1 Splitter m [Markup XMLToken Text]
forall (m :: * -> *). Monad m => Splitter m [Markup XMLToken Text]
XML.xmlAttributeValue

liftParallelPair :: MonadParallel m => 
                    String -> (PairBinder m -> c1 -> c2 -> c3) -> Component c1 -> Component c2 -> Component c3
liftParallelPair :: forall (m :: * -> *) c1 c2 c3.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
liftParallelPair String
name PairBinder m -> c1 -> c2 -> c3
combinator = String
-> (Bool -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
forall c1 c2 c3.
String
-> (Bool -> c1 -> c2 -> c3)
-> Component c1
-> Component c2
-> Component c3
Configuration.liftParallelPair String
name (\Bool
b-> PairBinder m -> c1 -> c2 -> c3
combinator (PairBinder m -> c1 -> c2 -> c3) -> PairBinder m -> c1 -> c2 -> c3
forall a b. (a -> b) -> a -> b
$ Bool -> PairBinder m
forall (m :: * -> *). MonadParallel m => Bool -> PairBinder m
chooseBinder Bool
b)

parallelRouterAndBranches :: MonadParallel m => 
                             String -> (PairBinder m -> c1 -> c2 -> c3 -> c4) 
                             -> Component c1 -> Component c2 -> Component c3 -> Component c4
parallelRouterAndBranches :: forall (m :: * -> *) c1 c2 c3 c4.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c3 -> c4)
-> Component c1
-> Component c2
-> Component c3
-> Component c4
parallelRouterAndBranches String
name PairBinder m -> c1 -> c2 -> c3 -> c4
combinator = 
   String
-> (Bool -> c1 -> c2 -> c3 -> c4)
-> Component c1
-> Component c2
-> Component c3
-> Component c4
forall c1 c2 c3 c4.
String
-> (Bool -> c1 -> c2 -> c3 -> c4)
-> Component c1
-> Component c2
-> Component c3
-> Component c4
Configuration.parallelRouterAndBranches String
name (\Bool
b-> PairBinder m -> c1 -> c2 -> c3 -> c4
combinator (PairBinder m -> c1 -> c2 -> c3 -> c4)
-> PairBinder m -> c1 -> c2 -> c3 -> c4
forall a b. (a -> b) -> a -> b
$ Bool -> PairBinder m
forall (m :: * -> *). MonadParallel m => Bool -> PairBinder m
chooseBinder Bool
b)

chooseBinder :: MonadParallel m => Bool -> PairBinder m
chooseBinder :: forall (m :: * -> *). MonadParallel m => Bool -> PairBinder m
chooseBinder Bool
parallel = if Bool
parallel then (x -> y -> m r) -> m x -> m y -> m r
PairBinder m
forall (m :: * -> *). MonadParallel m => PairBinder m
parallelBinder else (x -> y -> m r) -> m x -> m y -> m r
PairBinder m
forall (m :: * -> *). Monad m => PairBinder m
sequentialBinder

recursiveComponentTree :: MonadParallel m => String -> (PairBinder m -> c1 -> c2 -> c2) -> Component c1 -> Component c2
recursiveComponentTree :: forall (m :: * -> *) c1 c2.
MonadParallel m =>
String
-> (PairBinder m -> c1 -> c2 -> c2) -> Component c1 -> Component c2
recursiveComponentTree String
name PairBinder m -> c1 -> c2 -> c2
combinator = String -> (Bool -> c1 -> c2 -> c2) -> Component c1 -> Component c2
forall c1 c2.
String -> (Bool -> c1 -> c2 -> c2) -> Component c1 -> Component c2
Configuration.recursiveComponentTree String
name (\Bool
b-> PairBinder m -> c1 -> c2 -> c2
combinator (PairBinder m -> c1 -> c2 -> c2) -> PairBinder m -> c1 -> c2 -> c2
forall a b. (a -> b) -> a -> b
$ Bool -> PairBinder m
forall (m :: * -> *). MonadParallel m => Bool -> PairBinder m
chooseBinder Bool
b)