-- 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 original library design is based on paper -- http://conferences.idealliance.org/extreme/html/2006/Blazevic01/EML2006Blazevic01.html -- -- Mario Blažević, Streaming component combinators, Extreme Markup -- Languages, 2006. @package scc @version 0.3 -- | Module Foundation defines the pipe computations and their basic -- building blocks. module Control.Concurrent.SCC.Foundation class (Monad m) => ParallelizableMonad m parallelize :: (ParallelizableMonad m) => m a -> m b -> m (a, b) -- | 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 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 -- | 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 context m x r1 -> Consumer context 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 c m x r1 -> Consumer c m x r2 -> Pipe c m (r1, r2) -- | The pipeP function is equivalent to pipe, except the -- producer and consumer are run in parallel if resources -- allow. pipeP :: (ParallelizableMonad m) => Producer c m x r1 -> Consumer c m x r2 -> Pipe c 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 get' assumes that the argument source is not empty and -- returns the value the source yields. If the source is empty, the -- function throws an error. get' :: (Monad m, Typeable x) => Source context x -> Pipe context m x -- | 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 c x -> Sink c x -> Pipe c m () -- | pourMap is like pour that applies the function f -- to each argument before passing it into the sink. pourMap :: (Monad m, Typeable x, Typeable y) => (x -> y) -> Source c x -> Sink c y -> Pipe c m () -- | pourMapMaybe is to pourMap like -- Data.Maybe.mapMaybe is to Data.List.Map. pourMapMaybe :: (Monad m, Typeable x, Typeable y) => (x -> Maybe y) -> Source c x -> Sink c y -> 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 c x -> Sink c x -> Sink c x -> Pipe c m () -- | getList returns the list of all values generated by the source. getList :: (Monad m, Typeable x) => Source c 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 c x -> Pipe c m [x] -- | Like putList, except it puts the contents of the given -- Seq into the sink. putQueue :: (Monad m, Typeable x) => Seq x -> Sink c x -> Pipe c m [x] -- | consumeAndSuppress consumes the entire source ignoring the -- values it generates. consumeAndSuppress :: (Monad m, Typeable x) => Source c x -> Pipe c m () instance Show (Suspension context m r) instance (ParallelizableMonad m) => ParallelizableMonad (Pipe context m) instance (Monad m) => Monad (Pipe context m) instance ParallelizableMonad IO instance ParallelizableMonad Maybe instance ParallelizableMonad Identity module Control.Concurrent.SCC.ComponentTypes -- | The types of Component class carry metadata and can be -- configured to use a specific number of threads. class Component c name :: (Component c) => c -> String subComponents :: (Component c) => c -> [AnyComponent] maxUsableThreads :: (Component c) => c -> Int usingThreads :: (Component c) => Int -> c -> c usedThreads :: (Component c) => c -> Int cost :: (Component c) => c -> Int -- | BranchComponent is a type class representing all components -- that can act as consumers, namely Consumer, Transducer, -- and Splitter. class BranchComponent cc m x r | cc -> m x combineBranches :: (BranchComponent cc m x r) => String -> Int -> (forall c. Bool -> (Source c x -> Pipe c m r) -> (Source c x -> Pipe c m r) -> (Source c x -> Pipe c m r)) -> cc -> cc -> cc class LiftableComponent cx cy x y | cx -> x, cy -> y, cx y -> cy, cy x -> cx liftComponent :: (LiftableComponent cx cy x y) => cy -> cx -- | The Container class applies to two types where a first type -- value may contain values of the second type. class Container x y unwrap :: (Container x y, ParallelizableMonad m) => (Splitter m x (), Transducer m x y) rewrap :: (Container x y, ParallelizableMonad m) => Transducer m y x -- | AnyComponent is an existential type wrapper around a -- Component. data AnyComponent AnyComponent :: a -> AnyComponent -- | A component that performs a computation with no inputs nor outputs is -- a Performer. data Performer m r Performer :: String -> Int -> ComponentConfiguration -> (Int -> (ComponentConfiguration, forall c. Pipe c m r)) -> (forall c. Pipe c m r) -> Performer m r performerName :: Performer m r -> String performerMaxThreads :: Performer m r -> Int performerConfiguration :: Performer m r -> ComponentConfiguration performerUsingThreads :: Performer m r -> Int -> (ComponentConfiguration, forall c. Pipe c m r) perform :: Performer m r -> forall c. Pipe c m r -- | A component that consumes values from a Source is called -- Consumer. data Consumer m x r = Consumer {consumerData :: -- ComponentData (forall c. Source c x -> Pipe c m r), consume :: -- forall c. Source c x -> Pipe c m r} data Consumer m x r Consumer :: String -> Int -> ComponentConfiguration -> (Int -> (ComponentConfiguration, forall c. Source c x -> Pipe c m r)) -> (forall c. Source c x -> Pipe c m r) -> Consumer m x r consumerName :: Consumer m x r -> String consumerMaxThreads :: Consumer m x r -> Int consumerConfiguration :: Consumer m x r -> ComponentConfiguration consumerUsingThreads :: Consumer m x r -> Int -> (ComponentConfiguration, forall c. Source c x -> Pipe c m r) consume :: Consumer m x r -> forall c. Source c x -> Pipe c m r -- | A component that produces values and puts them into a Sink is -- called Producer. data Producer m x r Producer :: String -> Int -> ComponentConfiguration -> (Int -> (ComponentConfiguration, forall c. Sink c x -> Pipe c m r)) -> (forall c. Sink c x -> Pipe c m r) -> Producer m x r producerName :: Producer m x r -> String producerMaxThreads :: Producer m x r -> Int producerConfiguration :: Producer m x r -> ComponentConfiguration producerUsingThreads :: Producer m x r -> Int -> (ComponentConfiguration, forall c. Sink c x -> Pipe c m r) produce :: Producer m x r -> forall c. Sink c x -> Pipe c m r -- | 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 c x' arguments of a -- splitter are the same, the splitter must act as an identity transform. data Splitter m x b Splitter :: String -> Int -> ComponentConfiguration -> (Int -> (ComponentConfiguration, forall c. Source c x -> Sink c x -> Sink c x -> Sink c b -> Pipe c m [x])) -> (forall c. Source c x -> Sink c x -> Sink c x -> Sink c b -> Pipe c m [x]) -> Splitter m x b splitterName :: Splitter m x b -> String splitterMaxThreads :: Splitter m x b -> Int splitterConfiguration :: Splitter m x b -> ComponentConfiguration splitterUsingThreads :: Splitter m x b -> Int -> (ComponentConfiguration, forall c. Source c x -> Sink c x -> Sink c x -> Sink c b -> Pipe c m [x]) split :: Splitter m x b -> forall c. Source c x -> Sink c x -> Sink c x -> Sink c b -> Pipe c 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. data Transducer m x y Transducer :: String -> Int -> ComponentConfiguration -> (Int -> (ComponentConfiguration, forall c. Source c x -> Sink c y -> Pipe c m [x])) -> (forall c. Source c x -> Sink c y -> Pipe c m [x]) -> Transducer m x y transducerName :: Transducer m x y -> String transducerMaxThreads :: Transducer m x y -> Int transducerConfiguration :: Transducer m x y -> ComponentConfiguration transducerUsingThreads :: Transducer m x y -> Int -> (ComponentConfiguration, forall c. Source c x -> Sink c y -> Pipe c m [x]) transduce :: Transducer m x y -> forall c. Source c x -> Sink c y -> Pipe c m [x] data ComponentConfiguration ComponentConfiguration :: [AnyComponent] -> Int -> Int -> ComponentConfiguration componentChildren :: ComponentConfiguration -> [AnyComponent] componentThreads :: ComponentConfiguration -> Int componentCost :: ComponentConfiguration -> Int -- | A Markup value is produced to mark either a Start and -- End of a region of data, or an arbitrary Point in data. -- A Point is semantically equivalent to a Start -- immediately followed by End. The Content constructor -- wraps the actual data. data Boundary y Start :: y -> Boundary y End :: y -> Boundary y Point :: y -> Boundary y data Markup x y Content :: x -> Markup x y Markup :: (Boundary y) -> Markup x y type Parser m x b = Transducer m x (Markup x b) -- | Function liftPerformer takes a component name, maximum number -- of threads it can use, and its usingThreads method, and returns -- a Performer component. liftPerformer :: String -> Int -> (Int -> (ComponentConfiguration, forall c. Pipe c m r)) -> Performer m r -- | Function liftConsumer takes a component name, maximum number of -- threads it can use, and its usingThreads method, and returns a -- Consumer component. liftConsumer :: String -> Int -> (Int -> (ComponentConfiguration, forall c. Source c x -> Pipe c m r)) -> Consumer m x r -- | Function liftAtomicConsumer lifts a single-threaded -- consume function into a Consumer component. liftAtomicConsumer :: String -> Int -> (forall c. Source c x -> Pipe c m r) -> Consumer m x r -- | Function liftProducer takes a component name, maximum number of -- threads it can use, and its usingThreads method, and returns a -- Producer component. liftProducer :: String -> Int -> (Int -> (ComponentConfiguration, forall c. Sink c x -> Pipe c m r)) -> Producer m x r -- | Function liftAtomicProducer lifts a single-threaded -- produce function into a Producer component. liftAtomicProducer :: String -> Int -> (forall c. Sink c x -> Pipe c m r) -> Producer m x r -- | Function liftTransducer takes a component name, maximum number -- of threads it can use, and its usingThreads method, and returns -- a Transducer component. liftTransducer :: String -> Int -> (Int -> (ComponentConfiguration, forall c. Source c x -> Sink c y -> Pipe c m [x])) -> Transducer m x y -- | Function liftAtomicTransducer lifts a single-threaded -- transduce function into a Transducer component. liftAtomicTransducer :: String -> Int -> (forall c. Source c x -> Sink c y -> Pipe c m [x]) -> Transducer m x y -- | 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) => String -> (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) => String -> (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) => String -> (s -> x -> s) -> s -> (s -> 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) => String -> (state -> x -> (state, [y])) -> state -> Transducer m x y -- | Function liftSplitter lifts a splitter function into a full -- Splitter. liftSplitter :: (Monad m, Typeable x) => String -> Int -> (Int -> (ComponentConfiguration, forall c. Source c x -> Sink c x -> Sink c x -> Sink c b -> Pipe c m [x])) -> Splitter m x b -- | Function liftAtomicSplitter lifts a single-threaded -- split function into a Splitter component. liftAtomicSplitter :: (Monad m, Typeable x) => String -> Int -> (forall c. Source c x -> Sink c x -> Sink c x -> Sink c b -> Pipe c m [x]) -> Splitter m x b -- | Function liftStatelessSplitter takes a function that assigns a -- Boolean value to each input item and lifts it into a Splitter. liftStatelessSplitter :: (ParallelizableMonad m, Typeable x) => String -> (x -> Bool) -> Splitter m x b -- | Function liftStatefulSplitter takes a state-converting function -- that also assigns a Boolean value to each input item and lifts it into -- a Splitter. liftStatefulSplitter :: (ParallelizableMonad m, Typeable x) => String -> (state -> x -> (state, Bool)) -> state -> Splitter m x () -- | Show details of the given component's configuration. showComponentTree :: (Component c) => c -> String -- | Function optimalTwoParallelConfigurations configures two -- components assuming they can be run in parallel, splitting the given -- thread count between them, and returns the configured components, a -- ComponentConfiguration that can be used to build a new -- component from them, and a flag that indicates if they should be run -- in parallel or sequentially for optimal resource usage. optimalTwoParallelConfigurations :: (Component c1, Component c2) => Int -> c1 -> c2 -> (ComponentConfiguration, c1, c2, Bool) -- | Function optimalTwoParallelConfigurations configures two -- components, both of them with the full thread count, and returns the -- components and a ComponentConfiguration that can be used to -- build a new component from them. optimalTwoSequentialConfigurations :: (Component c1, Component c2) => Int -> c1 -> c2 -> (ComponentConfiguration, c1, c2) -- | Function optimalThreeParallelConfigurations configures three -- components assuming they can be run in parallel, splitting the given -- thread count between them, and returns the components, a -- ComponentConfiguration that can be used to build a new -- component from them, and a flag per component that indicates if it -- should be run in parallel or sequentially for optimal resource usage. optimalThreeParallelConfigurations :: (Component c1, Component c2, Component c3) => Int -> c1 -> c2 -> c3 -> (ComponentConfiguration, (c1, Bool), (c2, Bool), (c3, Bool)) -- | Given a Splitter, a Source, and three consumer -- functions, splitToConsumers runs the splitter on the source and -- feeds the splitter's outputs to its true, false, and -- edge sinks, respectively, to the three consumers. splitToConsumers :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Source c x -> (Source c x -> Pipe c m r1) -> (Source c x -> Pipe c m r2) -> (Source c b -> Pipe c m r3) -> Pipe c m ([x], r1, r2, r3) -- | Given a Splitter, a Source, and two consumer functions, -- splitInputToConsumers runs the splitter on the source and feeds -- the splitter's true and false outputs, respectively, to -- the two consumers. splitInputToConsumers :: (ParallelizableMonad m, Typeable x, Typeable b) => Bool -> Splitter m x b -> Source c x -> (Source c x -> Pipe c m [x]) -> (Source c x -> Pipe c m [x]) -> Pipe c m [x] instance Typeable2 Markup instance Typeable1 Boundary instance (Eq x, Eq y) => Eq (Markup x y) instance (Eq y) => Eq (Boundary y) instance (Show y) => Show (Boundary y) instance (ParallelizableMonad m, Typeable x) => BranchComponent (Splitter m x b) m x [x] instance BranchComponent (Transducer m x y) m x [x] instance (Monad m) => BranchComponent (Consumer m x ()) m x [x] instance (Monad m) => BranchComponent (Consumer m x r) m x r instance Component (Splitter m x b) instance Component (Transducer m x y) instance Component (Producer m x r) instance Component (Consumer m x r) instance Component (Performer m r) instance (Container x y, ParallelizableMonad m, Typeable x, Typeable y) => LiftableComponent (Splitter m x ()) (Splitter m y ()) x y instance (Container x y, ParallelizableMonad m, Typeable x, Typeable y) => LiftableComponent (Transducer m x x) (Transducer m y y) x y instance (Typeable x, Typeable y) => Container (Markup x y) x instance (Show y) => Show (Markup Char y) instance Functor Boundary instance Component AnyComponent -- | The Combinators module defines combinators applicable to -- Transducer and Splitter components defined in the -- Control.Concurrent.SCC.ComponentTypes module. module Control.Concurrent.SCC.Combinators -- | Converts a Splitter into a Transducer. Every input value -- x that the argument splitter sends to its true sink is -- converted to Left (x, True), every y sent to the -- splitter's false sink becomes Left (y, False), and any -- value e the splitter puts in its edge sink becomes -- Right e. splitterToMarker :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Transducer m x (Either (x, Bool) b) -- | Converts a Consumer into a Transducer with no output. consumeBy :: (Monad m, Typeable x) => Consumer m x r -> Transducer m x y -- | 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, Typeable x) => Producer m x r -> Transducer m x x -- | 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, Typeable x) => Producer m x r -> Transducer m x x -- | 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, Typeable x, Typeable y) => Producer m y r -> Transducer m x y -- | Class PipeableComponentPair applies to any two components that -- can be combined into a third component with the following properties: -- -- class PipeableComponentPair m :: (* -> *) w c1 c2 c3 | c1 c2 -> c3, c1 c3 -> c2, c2 c3 -> c2, c1 -> m w, c2 -> m w, c3 -> m (>->) :: (PipeableComponentPair m w c1 c2 c3) => c1 -> c2 -> c3 -- | Class JoinableComponentPair applies to any two components that -- can be combined into a third component with the following properties: -- -- class (Monad m, CompatibleSignature c1 t1 m x y, CompatibleSignature c2 t2 m x y, CompatibleSignature c3 t3 m x y) => JoinableComponentPair t1 t2 t3 m x y c1 c2 c3 | c1 c2 -> c3, c1 -> t1 m, c2 -> t2 m, c3 -> t3 m x y, t1 m x y -> c1, t2 m x y -> c2, t3 m x y -> c3 join :: (JoinableComponentPair t1 t2 t3 m x y c1 c2 c3) => c1 -> c2 -> c3 sequence :: (JoinableComponentPair t1 t2 t3 m x y c1 c2 c3) => c1 -> c2 -> c3 -- | 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 :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Splitter m x b -- | 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. (>&) :: (ParallelizableMonad m, Typeable x, Typeable b1, Typeable b2) => Splitter m x b1 -> Splitter m x b2 -> Splitter m x (b1, b2) -- | A >| combinator's input value can reach its false -- sink only by going through both argument splitters' false -- sinks. (>|) :: (ParallelizableMonad m, Typeable x, Typeable b1, Typeable b2) => Splitter m x b1 -> Splitter m x b2 -> Splitter m x (Either b1 b2) -- | Combinator && is a pairwise logical conjunction of two -- splitters run in parallel on the same input. (&&) :: (ParallelizableMonad m, Typeable x, Typeable b1, Typeable b2) => Splitter m x b1 -> Splitter m x b2 -> Splitter m x (b1, b2) -- | Combinator || is a pairwise logical disjunction of two -- splitters run in parallel on the same input. (||) :: (ParallelizableMonad m, Typeable x, Typeable b1, Typeable b2) => Splitter m x b1 -> Splitter m x b2 -> Splitter m x (Either b1 b2) ifs :: (ParallelizableMonad m, Typeable x, Typeable b, BranchComponent cc m x [x]) => Splitter m x b -> cc -> cc -> cc wherever :: (ParallelizableMonad m, Typeable x, Typeable b) => Transducer m x x -> Splitter m x b -> Transducer m x x unless :: (ParallelizableMonad m, Typeable x, Typeable b) => Transducer m x x -> Splitter m x b -> Transducer m x x select :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> 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 :: (ParallelizableMonad m, Typeable x, Typeable b) => Transducer m x x -> Splitter m x b -> 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, an input value would either -- not loop at all or it would loop forever. nestedIn :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Splitter m x b -> Splitter m x b -- | 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 :: (ParallelizableMonad m, Typeable x, Typeable b, BranchComponent cc m x [x]) => Splitter m x b -> cc -> cc -> cc -- | 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 :: (ParallelizableMonad m, Typeable x, Typeable b1, Typeable b2) => Splitter m x b1 -> Splitter m x b2 -> Splitter m x b1 -- | 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 :: (ParallelizableMonad m, Typeable x, Typeable b1, Typeable b2) => Splitter m x b1 -> Splitter m x b2 -> Splitter m x b1 -- | 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 :: (ParallelizableMonad m, Typeable x, Typeable b1, Typeable b2) => Splitter m x b1 -> Splitter m x b2 -> Splitter m x (b1, b2) -- | 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 :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Splitter m x b -- | 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 :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Splitter m x b -- | 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 :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Splitter m x b -- | 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 :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Splitter m x b -- | 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 :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Splitter m x b -- | 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 :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Splitter m x b -- | 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 :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Splitter m x b -- | Splitter 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 :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Splitter m x (Maybe b) -- | Splitter 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 :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Splitter m x (Maybe b) -- | 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. (...) :: (ParallelizableMonad m, Typeable x, Typeable b1, Typeable b2) => Splitter m x b1 -> Splitter m x b2 -> Splitter m x b1 -- | Converts a splitter into a parser. parseRegions :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x b -> Parser m x b -- | Converts a boundary-marking splitter into a parser. parseNestedRegions :: (ParallelizableMonad m, Typeable x, Typeable b) => Splitter m x (Boundary b) -> Parser m x b -- | Runs the second argument on every contiguous region of input source -- (typically produced by splitterToMarker) whose all values -- either match Left (_, True) or Left (_, False). groupMarks :: (ParallelizableMonad m, Typeable x, Typeable b) => Source c (Either (x, Bool) b) -> (Maybe (Maybe b) -> Source c x -> Pipe c m r) -> Pipe c m () instance (ParallelizableMonad m, Typeable x, Typeable y) => JoinableComponentPair (ConsumerType ()) (ProducerType ()) TransducerType m [x] [y] (Consumer m x ()) (Producer m y ()) (Transducer m x y) instance (ParallelizableMonad m, Typeable x, Typeable y) => JoinableComponentPair (ProducerType ()) (ConsumerType ()) TransducerType m [x] [y] (Producer m y ()) (Consumer m x ()) (Transducer m x y) instance (ParallelizableMonad m, Typeable x, Typeable y) => JoinableComponentPair TransducerType (ConsumerType ()) TransducerType m [x] [y] (Transducer m x y) (Consumer m x ()) (Transducer m x y) instance (ParallelizableMonad m, Typeable x, Typeable y) => JoinableComponentPair (ConsumerType ()) TransducerType TransducerType m [x] [y] (Consumer m x ()) (Transducer m x y) (Transducer m x y) instance (ParallelizableMonad m, Typeable x, Typeable y) => JoinableComponentPair TransducerType (ProducerType ()) TransducerType m [x] [y] (Transducer m x y) (Producer m y ()) (Transducer m x y) instance (ParallelizableMonad m, Typeable x, Typeable y) => JoinableComponentPair (ProducerType ()) TransducerType TransducerType m [x] [y] (Producer m y ()) (Transducer m x y) (Transducer m x y) instance (ParallelizableMonad m, Typeable x, Typeable y) => JoinableComponentPair TransducerType (PerformerType r) TransducerType m [x] [y] (Transducer m x y) (Performer m r) (Transducer m x y) instance (ParallelizableMonad m, Typeable x, Typeable y) => JoinableComponentPair (PerformerType r) TransducerType TransducerType m [x] [y] (Performer m r) (Transducer m x y) (Transducer m x y) instance (ParallelizableMonad m, Typeable x) => JoinableComponentPair (ConsumerType r1) (PerformerType r2) (ConsumerType r2) m [x] () (Consumer m x r1) (Performer m r2) (Consumer m x r2) instance (ParallelizableMonad m, Typeable x) => JoinableComponentPair (PerformerType r1) (ConsumerType r2) (ConsumerType r2) m [x] () (Performer m r1) (Consumer m x r2) (Consumer m x r2) instance (ParallelizableMonad m, Typeable x) => JoinableComponentPair (ProducerType r1) (PerformerType r2) (ProducerType r2) m () [x] (Producer m x r1) (Performer m r2) (Producer m x r2) instance (ParallelizableMonad m, Typeable x) => JoinableComponentPair (PerformerType r1) (ProducerType r2) (ProducerType r2) m () [x] (Performer m r1) (Producer m x r2) (Producer m x r2) instance (ParallelizableMonad m) => JoinableComponentPair (PerformerType r1) (PerformerType r2) (PerformerType r2) m () () (Performer m r1) (Performer m r2) (Performer m r2) instance (ParallelizableMonad m, Typeable x, Typeable y) => JoinableComponentPair TransducerType TransducerType TransducerType m [x] [y] (Transducer m x y) (Transducer m x y) (Transducer m x y) instance (ParallelizableMonad m, Typeable x) => JoinableComponentPair (ConsumerType ()) (ConsumerType ()) (ConsumerType ()) m [x] () (Consumer m x ()) (Consumer m x ()) (Consumer m x ()) instance (Monad m, Typeable x) => JoinableComponentPair (ProducerType r1) (ProducerType r2) (ProducerType r2) m () [x] (Producer m x r1) (Producer m x r2) (Producer m x r2) instance CompatibleSignature (Transducer m x y) TransducerType m [x] [y] instance (AnyListOrUnit y) => CompatibleSignature (Producer m x r) (ProducerType r) m y [x] instance (AnyListOrUnit y) => CompatibleSignature (Consumer m x r) (ConsumerType r) m [x] y instance (AnyListOrUnit x, AnyListOrUnit y) => CompatibleSignature (Performer m r) (PerformerType r) m x y instance AnyListOrUnit () instance AnyListOrUnit [x] instance (ParallelizableMonad m) => PipeableComponentPair m y (Transducer m x y) (Transducer m y z) (Transducer m x z) instance (ParallelizableMonad m, Typeable x, Typeable y) => PipeableComponentPair m x (Producer m x r) (Transducer m x y) (Producer m y r) instance (ParallelizableMonad m, Typeable x, Typeable y) => PipeableComponentPair m y (Transducer m x y) (Consumer m y r) (Consumer m x r) instance (ParallelizableMonad m, Typeable x) => PipeableComponentPair m x (Producer m x ()) (Consumer m x ()) (Performer m ()) -- | Module Components defines primitive components of -- Producer, Consumer, Transducer and -- Splitter types, defined in the Foundation and -- ComponentTypes modules. module Control.Concurrent.SCC.Components -- | Used by parseSubstring to distinguish between overlapping -- substrings. data OccurenceTag -- | fromList produces the contents of the given list argument. fromList :: (Monad m, Typeable x) => [x] -> Producer m x [x] -- | Consumer toList copies the given source into a list. toList :: (Monad m, Typeable x) => Consumer m x [x] -- | 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. The argument doClose determines if | -- handle should be closed when the handle is consumed or the sink -- closed. fromHandle :: Handle -> Bool -> 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. The argument doClose determines if | -- handle should be closed once the entire source is consumed and -- copied. toHandle :: Handle -> Bool -> Consumer IO Char () -- | Consumer toStdOut copies the given source into the standard -- output. toStdOut :: Consumer IO Char () -- | The suppress consumer suppresses all input it receives. It is -- equivalent to substitute [] suppress :: (Monad m, Typeable x) => Consumer m x () -- | The erroneous consumer reports an error if any input reaches -- it. erroneous :: (Monad m, Typeable x) => String -> Consumer m x () -- | Transducer asis passes its input through unmodified. asis :: (Monad m, Typeable x) => Transducer m x x -- | Transducer parse prepares input content for subsequent parsing. parse :: (Monad m, Typeable x, Typeable y) => Transducer m x (Markup x y) -- | Transducer unparse removes all markup from its input and passes -- the content through. unparse :: (Monad m, Typeable x, Typeable y) => Transducer m (Markup x y) x -- | 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 :: (ParallelizableMonad m, Eq x, Typeable x) => [x] -> Parser m x OccurenceTag -- | Splitter everything feeds its entire input into its true -- sink. everything :: (ParallelizableMonad m, Typeable x) => Splitter m x () -- | Splitter nothing feeds its entire input into its false -- sink. nothing :: (ParallelizableMonad m, Typeable x) => Splitter m x () -- | Splitter marked passes all marked-up input sections to its -- true sink, and all unmarked input to its false sink. marked :: (ParallelizableMonad m, Typeable x, Typeable y, Eq y) => Splitter m (Markup x y) () -- | Splitter 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 :: (ParallelizableMonad m, Typeable x, Typeable y, Eq y) => Splitter m (Markup x y) () -- | Splitter 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 :: (ParallelizableMonad m, Typeable x, Typeable y, Eq y) => (y -> Bool) -> Splitter m (Markup x y) () -- | Splitter 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 :: (ParallelizableMonad m, Typeable x, Typeable y, Eq y) => (y -> Bool) -> Splitter m (Markup x y) () -- | Splitter one feeds all input values to its true sink, -- treating every value as a separate section. one :: (ParallelizableMonad 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, both are sent -- to true and each is preceded by an edge. substring :: (ParallelizableMonad 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 -- | Same as concatenate except it inserts the given separator list -- between every two input lists. 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 :: (ParallelizableMonad m) => Splitter m Char () -- | Splitter letters feeds all alphabetical characters into its -- true sink, all other characters into false. letters :: (ParallelizableMonad m) => Splitter m Char () -- | Splitter digits feeds all digits into its true sink, all -- other characters into false. digits :: (ParallelizableMonad 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 :: (ParallelizableMonad m) => Splitter m Char () -- | Splitter nonEmptyLine feeds line-ends into its false -- sink, and all other characters into true. nonEmptyLine :: (ParallelizableMonad 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 -- | Converts each input value x to show x. toString :: (Monad m, Show x, Typeable x) => Transducer m x String -- | The constant cost of each I/O-performing component. ioCost :: Int instance Typeable OccurenceTag instance Eq OccurenceTag instance Show OccurenceTag instance Enum OccurenceTag -- | Module XMLComponents defines primitive components for parsing -- and manipulating XML. module Control.Concurrent.SCC.XMLComponents data Token StartTag :: Token EndTag :: Token EmptyTag :: Token ElementName :: Token AttributeName :: Token AttributeValue :: Token EntityReferenceToken :: Token EntityName :: Token ProcessingInstruction :: Token ProcessingInstructionText :: Token Comment :: Token CommentText :: Token StartMarkedSectionCDATA :: Token EndMarkedSection :: Token ErrorToken :: String -> Token -- | The tokens splitter distinguishes XML markup from data content. -- It is used by parseTokens. tokens :: (ParallelizableMonad m) => Splitter m Char (Boundary Token) -- | The XML token parser. This parser converts plain text to parsed text, -- which is a precondition for using the remaining XML components. parseTokens :: (ParallelizableMonad m) => Parser m Char Token -- | Converts an XML entity name into the text value it represents: -- expandEntity "lt" = "<". expandEntity :: String -> String -- | Escapes a character for inclusion into an XML attribute value. escapeAttributeCharacter :: Char -> String -- | Escapes a character for inclusion into the XML data content. escapeContentCharacter :: Char -> String -- | Splits all top-level elements with all their content to true, -- all other input to false. element :: (Monad m) => Splitter m (Markup Char Token) () -- | Splits the content of all top-level elements to true, their -- tags and intervening input to false. elementContent :: (Monad m) => Splitter m (Markup Char Token) () -- | Splits every element name, including the names of nested elements and -- names in end tags, to true, all the rest of input to -- false. elementName :: (ParallelizableMonad m) => Splitter m (Markup Char Token) () -- | Splits every attribute specification to true, everything else -- to false. attribute :: (ParallelizableMonad m) => Splitter m (Markup Char Token) () -- | Splits every attribute name to true, all the rest of input to -- false. attributeName :: (ParallelizableMonad m) => Splitter m (Markup Char Token) () -- | Splits every attribute value, excluding the quote delimiters, to -- true, all the rest of input to false. attributeValue :: (ParallelizableMonad m) => Splitter m (Markup Char Token) () -- | Similiar to (having element), except it runs -- the argument splitter only on each element's start tag, not on the -- entire element with its content. elementHavingTag :: (ParallelizableMonad m, Typeable b) => Splitter m (Markup Char Token) b -> Splitter m (Markup Char Token) b -- | Behaves like having, but the right-hand splitter works on plain -- instead of marked-up text. This allows regular Char splitters -- to be applied to parsed XML. havingText :: (ParallelizableMonad m, Typeable b1, Typeable b2) => Splitter m (Markup Char Token) b1 -> Splitter m Char b2 -> Splitter m (Markup Char Token) b1 -- | Behaves like havingOnly, but the right-hand splitter works on -- plain instead of marked-up text. This allows regular Char -- splitters to be applied to parsed XML. havingOnlyText :: (ParallelizableMonad m, Typeable b1, Typeable b2) => Splitter m (Markup Char Token) b1 -> Splitter m Char b2 -> Splitter m (Markup Char Token) b1 instance Typeable Token instance Eq Token instance Show Token