-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Streaming component combinators -- -- SCC is a layered library of Streaming Component Combinators. The -- lowest layer defines a Pipe monad transformer that enables building of -- producer-consumer coroutine pairs. The next layer adds streaming -- component types, a number of primitive streaming components and a set -- of component combinators. Finally, there is an executable that exposes -- all functionality in a command-line shell. -- -- The library design is based on paper -- http://www.idealliance.org/papers/extreme/Proceedings/html/2006/Blazevic01/EML2006Blazevic01.html -- -- Mario Blažević, Streaming component combinators, Extreme Markup -- Languages, 2006. @package scc @version 0.1 -- | Module Foundation defines the pipe computations and their basic -- building blocks. module Control.Concurrent.SCC.Foundation -- | Pipe represents the type of monadic computations that can be -- split into co-routining computations using function pipe. The -- context type parameter delimits the scope of the computation. data (Monad m) => Pipe context m r -- | A Source is the read-only end of a Pipe communication -- channel. data Source context x -- | A Sink is the write-only end of a Pipe communication -- channel. data Sink context x -- | A computation that consumes values from a Source is called -- Consumer. type Consumer m x r = forall c. Source c x -> Pipe c m r -- | A computation that produces values and puts them into a Sink is -- called Producer. type Producer m x r = forall c. Sink c x -> Pipe c m r -- | The pipe function splits the computation into two concurrent -- parts, producer and consumer. The producer is -- given a Sink to put values into, and consumer a -- Source to get those values from. Once producer and consumer -- both complete, pipe returns their paired results. pipe :: (Monad m) => Producer m x r1 -> Consumer m x r2 -> Pipe context m (r1, r2) -- | The pipeD function is same as pipe, with an additional -- description argument. pipeD :: (Monad m) => String -> Producer m x r1 -> Consumer m x r2 -> Pipe context m (r1, r2) -- | Function get tries to get a value from the given Source -- argument. The intervening Pipe computations suspend all the way -- to the pipe function invocation that created the source. The -- result of get is Nothing iff the argument source is -- empty. get :: (Monad m, Typeable x) => Source context' x -> Pipe context m (Maybe x) getSuccess :: (Monad m, Typeable x) => Source context' x -> (x -> Pipe context m ()) -> Pipe context m () -- | Function canPut checks if the argument sink accepts values, -- i.e., whether a put operation would succeed on the sink. canPut :: (Monad m, Typeable x) => Sink context' x -> Pipe context m Bool -- | Function put tries to put a value into the given sink. The -- intervening Pipe computations suspend up to the pipe -- invocation that has created the argument sink. The result of -- put indicates whether the operation succeded. put :: (Monad m, Typeable x) => Sink context' x -> x -> Pipe context m Bool -- | Function liftPipe lifts a value of the underlying monad type -- into a Pipe computation. liftPipe :: (Monad m) => m r -> Pipe context m r -- | Function runPipes runs the given computation involving pipes -- and returns the final result. The context argument ensures that -- no suspended computation can escape its scope. runPipes :: (Monad m) => (forall context. Pipe context m r) -> m r -- | A utility function wrapping if-then-else, useful for handling monadic -- truth values cond :: a -> a -> Bool -> a -- | A utility function, useful for handling monadic list values where -- empty list means success whenNull :: (Monad m) => m [a] -> [a] -> m [a] -- | pour copies all data from the source argument into the -- sink argument, as long as there is anything to copy and the -- sink accepts it. pour :: (Monad m, Typeable x) => Source c1 x -> Sink c2 x -> Pipe c m () -- | tee is similar to pour except it distributes every input -- value from the source arguments into both sink1 and -- sink2. tee :: (Monad m, Typeable x) => Source c1 x -> Sink c2 x -> Sink c3 x -> Pipe c m () -- | getList returns the list of all values generated by the source. getList :: (Monad m, Typeable x) => Source c1 x -> Pipe c m [x] -- | putList puts entire list into its sink argument, as long -- as the sink accepts it. The remainder that wasn't accepted by the sink -- is the result value. putList :: (Monad m, Typeable x) => [x] -> Sink c1 x -> Pipe c m [x] -- | consumeAndSuppress consumes the entire source ignoring the -- values it generates. consumeAndSuppress :: (Monad m, Typeable x) => Source c1 x -> Pipe c m () instance Show (Suspension context m r) instance (Monad m) => Monad (Pipe context m) module Control.Concurrent.SCC.ComponentTypes -- | The Splitter 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 arguments of a splitter -- are the same, the splitter must act as an identity transform. data (Monad m) => Splitter m x Splitter :: (forall c1 c2 c3 context. Source c1 x -> Sink c2 x -> Sink c3 x -> Pipe context m [x]) -> (forall c1 c2 c3 context. Source c1 x -> Sink c2 (Maybe x) -> Sink c3 (Maybe x) -> Pipe context m [x]) -> Splitter m x split :: Splitter m x -> forall c1 c2 c3 context. Source c1 x -> Sink c2 x -> Sink c3 x -> Pipe context m [x] splitSections :: Splitter m x -> forall c1 c2 c3 context. Source c1 x -> Sink c2 (Maybe x) -> Sink c3 (Maybe x) -> Pipe context m [x] -- | The Transducer type represents computations that transform data -- and return no result. A transducer must continue consuming the given -- source and feeding the sink while there is data. newtype (Monad m) => Transducer m x y Transducer :: (forall c1 c2 context. Source c1 x -> Sink c2 y -> Pipe context m [x]) -> Transducer m x y transduce :: Transducer m x y -> forall c1 c2 context. Source c1 x -> Sink c2 y -> Pipe context m [x] -- | Function lift121Transducer takes a function that maps one input -- value to one output value each, and lifts it into a Transducer. lift121Transducer :: (Monad m, Typeable x, Typeable y) => (x -> y) -> Transducer m x y -- | Function liftStatelessTransducer takes a function that maps one -- input value into a list of output values, and lifts it into a -- Transducer. liftStatelessTransducer :: (Monad m, Typeable x, Typeable y) => (x -> [y]) -> Transducer m x y -- | Function liftFoldTransducer creates a stateful transducer that -- produces only one output value after consuming the entire input. -- Similar to Data.List.foldl liftFoldTransducer :: (Monad m, Typeable x, Typeable y) => (y -> x -> y) -> y -> Transducer m x y -- | Function liftStatefulTransducer constructs a Transducer -- from a state-transition function and the initial state. The transition -- function may produce arbitrary output at any transition step. liftStatefulTransducer :: (Monad m, Typeable x, Typeable y) => (state -> x -> (state, [y])) -> state -> Transducer m x y -- | Function liftSimpleSplitter lifts a simple, non-sectioning -- splitter function into a full Splitter liftSimpleSplitter :: (Monad m, Typeable x) => (forall c1 c2 c3 context. Source c1 x -> Sink c2 x -> Sink c3 x -> Pipe context m [x]) -> Splitter m x -- | Function liftSectionSplitter lifts a sectioning splitter -- function into a full Splitter liftSectionSplitter :: (Monad m, Typeable x) => (forall c1 c2 c3 context. Source c1 x -> Sink c2 (Maybe x) -> Sink c3 (Maybe x) -> Pipe context m [x]) -> Splitter m x -- | Function liftStatelessSplitter takes a function that assigns a -- Boolean value to each input item and lifts it into a Splitter liftStatelessSplitter :: (Monad m, Typeable x) => (x -> Bool) -> Splitter m x -- | Module Components defines primitive components of -- Producer, Consumer, Transducer and -- Splitter types, defined in the Foundation and -- ComponentTypes modules. module Control.Concurrent.SCC.Components -- | Producer fromFile opens the named file and feeds the given sink -- from its contents. fromFile :: String -> Producer IO Char () -- | Producer fromHandle feeds the given sink from the open file -- handle. fromHandle :: Handle -> Producer IO Char () -- | Producer fromStdIn feeds the given sink from the standard -- input. fromStdIn :: Producer IO Char () -- | Consumer appendFile opens the name file and appends the given -- source to it. appendFile :: String -> Consumer IO Char () -- | Consumer toFile opens the named file and copies the given -- source into it. toFile :: String -> Consumer IO Char () -- | Consumer toHandle copies the given source into the open file -- handle. toHandle :: Handle -> Consumer IO Char () -- | Consumer toStdOut copies the given source into the standard -- output. toStdOut :: Consumer IO Char () toPrint :: (Show x, Typeable x) => Consumer IO x () -- | Transducer asis passes its input through unmodified. asis :: (Monad m, Typeable x) => Transducer m x x -- | The suppress transducer suppresses all input it receives. It is -- equivalent to substitute [] suppress :: (Monad m, Typeable x, Typeable y) => Transducer m x y -- | The erroneous transducer reports an error if any input reaches -- it. erroneous :: (Monad m, Typeable x) => Transducer m x x -- | Transducer prepend passes its input unmodified, except for -- prepending contents of the given list parameter before it. prepend :: (Monad m, Typeable x) => [x] -> Transducer m x x -- | Transducer append passes its input unmodified, except for -- appending contents of the given list parameter to its end. append :: (Monad m, Typeable x) => [x] -> Transducer m x x -- | The substitute transducer replaces its whole input by its -- parameter. substitute :: (Monad m, Typeable x, Typeable y) => [y] -> Transducer m x y -- | Splitter allTrue feeds its entire input into its true -- sink. allTrue :: (Monad m, Typeable x) => Splitter m x -- | Splitter allFalse feeds its entire input into its false -- sink. allFalse :: (Monad m, Typeable x) => Splitter m x -- | Splitter one feeds all input values to its true sink, -- treating every value as a separate section. one :: (Monad m, Typeable x) => Splitter m x -- | Splitter 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, only the first -- one wins. substring :: (Monad m, Eq x, Typeable x) => [x] -> Splitter m x -- | Splitter substringMatch feeds to its true sink all input -- parts that match the contents of the given list argument. If two -- overlapping parts of the input match the argument, both are considered -- true. substringMatch :: (Monad m, Eq x, Typeable x) => [x] -> Splitter m x -- | Transducer group collects all its input values into a single -- list. group :: (Monad m, Typeable x) => Transducer m x [x] -- | Transducer concatenate flattens the input stream of lists of -- values into the output stream of values. concatenate :: (Monad m, Typeable x) => Transducer m [x] x concatSeparate :: (Monad m, Typeable x) => [x] -> Transducer m [x] x -- | The lowercase transforms all uppercase letters in the input to -- lowercase, leaving the rest unchanged. lowercase :: (Monad m) => Transducer m Char Char -- | The uppercase transforms all lowercase letters in the input to -- uppercase, leaving the rest unchanged. uppercase :: (Monad m) => Transducer m Char Char -- | Splitter whitespace feeds all white-space characters into its -- true sink, all others into false. whitespace :: (Monad m) => Splitter m Char -- | Splitter letters feeds all alphabetical characters into its -- true sink, all other characters into false. letters :: (Monad m) => Splitter m Char -- | Splitter digits feeds all digits into its true sink, all -- other characters into false. digits :: (Monad m) => Splitter m Char -- | 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) => Splitter m Char -- | Splitter nonEmptyLine feeds line-ends into its false -- sink, and all other characters into true. nonEmptyLine :: (Monad m) => Splitter m Char -- | The count transducer counts all its input values and outputs -- the final tally. count :: (Monad m, Typeable x) => Transducer m x Integer toString :: (Monad m, Show x, Typeable x) => Transducer m x String -- | The Combinators module defines combinators applicable to -- Transducer and Splitter components defined in the -- ComponentTypes module. module Control.Concurrent.SCC.Combinators -- | The result of combinator ->> is a consumer that acts as a -- composition of the given transducer and consumer arguments. (->>) :: (Monad m, Typeable x, Typeable y) => Transducer m x y -> Consumer m y r -> Consumer m x r -- | The result of combinator <<- is a producer that acts as a -- composition of the given transducer and producer arguments. (<<-) :: (Monad m, Typeable x, Typeable y) => Transducer m x y -> Producer m x r -> Producer m y r -- | 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. (>->) :: (Monad m) => Transducer m x y -> Transducer m y z -> Transducer m x z -- | 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. join :: (Monad m, Typeable x) => Transducer m x y -> Transducer m x y -> Transducer m x y -- | 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, Typeable x) => Splitter m x -> Splitter m x -- | 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 x -- | A >| combinator's input value can reach its false -- sink only by going through both argument splitters' false -- sinks. (>|) :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x -- | 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 x -- | Combinator || is a pairwise logical disjunction of two -- splitters run in parallel on the same input. (||) :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x -- | 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. 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 -- | 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 :: (Monad m, Typeable x) => Transducer m x x -> Splitter m x -> Transducer m x x -- | 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. nestedIn :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x -- | 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 :: (Monad m, Typeable x, Typeable y) => Splitter m x -> Transducer m x y -> Transducer m x y -> Transducer m x y -- | 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 :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x -- | 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 :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x -- | Combinator followedBy treats its argument Splitters 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. followedBy :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x -- | The even combinator takes every input section that its argument -- splitters 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, Typeable x) => Splitter m x -> Splitter m x -- | 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, Typeable x) => Splitter m x -> Splitter m x -- | 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. uptoFirst :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -- | 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, Typeable x) => Splitter m x -> Splitter m x -- | 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, Typeable x) => Splitter m x -> Splitter m x -- | 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, Typeable x) => Splitter m x -> Splitter m x -- | 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, Typeable x) => Splitter m x -> Splitter m x -- | 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. between :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x -- | Combinator ... is similar to between, except it passes -- to true the delimiting sections as well as all input between -- them. (...) :: (Monad m, Typeable x) => Splitter m x -> Splitter m x -> Splitter m x