-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Effectful, iteratee-inspired stream processing based on a free monad. -- @package tubes @version 0.2.1.0 module Tubes.Core -- | A Tube is a computation which can -- --
-- data TubeF a b k -- = Await (a -> k) -- :: (a -> k) -> TubeF a b k -- | Yield (b , k) -- :: (b , k) -> TubeF a b k -- ---- -- The type signatures for the two value constructors should bear a -- strong resemblance to the actual type signature of runT. -- Instead of encoding tubes as structures which build up when composed, -- a TubeF is a control flow mechanism which picks one of two -- provided continuations. -- -- People using this library should never have to contend with these -- details but it is worth mentioning. newtype TubeF a b k TubeF :: (forall r. ((a -> k) -> r) -> ((b, k) -> r) -> r) -> TubeF a b k runT :: TubeF a b k -> forall r. ((a -> k) -> r) -> ((b, k) -> r) -> r -- | A computation which only yields and never awaits type Source b m r = forall x. Tube x b m r -- | A computation which only awaits and never yields. type Sink a m r = forall x. Tube a x m r -- | A computation which neither yields nor awaits type Action m r = forall x. Tube x x m r -- | run is shorter than runFreeT and who knows, maybe it'll -- change some day run :: FreeT f m a -> m (FreeF f a (FreeT f m a)) -- | Command to wait for a new value upstream await :: Monad m => Tube a b m a -- | Command to send a value downstream yield :: Monad m => b -> Tube a b m () -- | Convert a list to a Source each :: (Monad m, Foldable t) => t b -> Tube a b m () -- | Enumerate yielded values into a continuation, creating a new -- Source for :: Monad m => Tube a b m r -> (b -> Tube a c m s) -> Tube a c m r -- | Compose two tubes into a new tube. (><) :: Monad m => Tube a b m r -> Tube b c m r -> Tube a c m r -- | Connect a task to a continuation yielding another task; see -- >< (>-) :: Monad m => Tube a b m r -> (b -> Tube b c m r) -> Tube a c m r -- | Infix version of for (~>) :: Monad m => Tube a b m r -> (b -> Tube a c m s) -> Tube a c m r -- | Constructor for source computations yieldF :: b -> k -> TubeF a b k -- | Constructor for sink computations awaitF :: (a -> k) -> TubeF a b k -- | This performs a neat trick: a Tube with a return type -- a will be turned into a new Tube containing the -- underlying TubeF value. -- -- In this way the >< and >- functions can replace -- the () return value with a continuation and recursively -- traverse the computation until a final result is reached. liftT :: (MonadTrans t, Monad m) => FreeT f m a -> t m (FreeF f a (FreeT f m a)) instance Functor (TubeF a b) module Tubes.Util -- | Continuously relays any values it receives. Iteratee identity. cat :: Monad m => Tube a a m r -- | Transforms all incoming values according to some function. map :: Monad m => (a -> b) -> Tube a b m r -- | Refuses to yield the first n values it receives. drop :: Monad m => Int -> Tube a a m r -- | Relay only the first n elements of a stream. take :: Monad m => Int -> Tube a a m () -- | Terminates the stream upon receiving a value violating the predicate takeWhile :: Monad m => (a -> Bool) -> Tube a a m () -- | Yields only values satisfying some predicate. filter :: Monad m => (a -> Bool) -> Tube a a m r -- | Strict left-fold of a stream. Note that the actual return type of the -- source is not relevant, only the intermediate yield type. reduce :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Source a m () -> m b -- | Similar to each except it explicitly marks the stream as -- exhausted every :: (Foldable t, Monad m) => t b -> Tube a (Maybe b) m () -- | Source of Strings from stdin. This is mostly for debugging / -- ghci example purposes. prompt :: Source String IO () -- | Sink for Strings to stdout. This is mostly for debugging / ghci -- example purposes. display :: Sink String IO () -- | Taps the next value from a source, maybe. unyield :: Monad m => FreeT (TubeF x b) m () -> m (Maybe (b, FreeT (TubeF x b) m ())) module Tubes.Pump -- | A Pump is the dual to a Tube: where a Tube is a -- computation manipulating a stream of values, a Pump can be -- situated on either end of a tube to both insert values when requested -- and handle any yielded results. -- -- This module is subject to change before I upload `0.2.0.0` to Hackage. type Pump a b = CofreeT (PumpF a b) data PumpF a b k PumpF :: (a, k) -> (b -> k) -> PumpF a b k recvF :: PumpF a b k -> (a, k) sendF :: PumpF a b k -> (b -> k) -- | Creates a Pump for a Tube using a comonadic seed value, -- a function to give it more data upon request, and a function to handle -- any yielded results. . Values received from the Tube may be -- altered and sent back into the tube, hence this mechanism does act -- like something of a pump. pump :: Comonad w => w a -> (w a -> (b, w a)) -> (w a -> c -> w a) -> Pump b c w a -- | Pull a value from a Pump, along with the rest of the -- Pump. recv :: Comonad w => Pump a b w r -> (a, Pump a b w r) -- | Send a value into a Pump, effectively re-seeding the stream. send :: Comonad w => Pump a b w r -> b -> Pump a b w r -- | Given a suitably matching Tube and Pump, you can use the -- latter to execute the former. runPump :: (Comonad w, Monad m) => (x -> y -> r) -> Pump a b w x -> Tube a b m y -> m r instance Functor (PumpF a b) instance Pairing (PumpF a b) (TubeF a b) instance Pairing ((,) a) ((->) a) instance Pairing ((->) a) ((,) a) instance Pairing Identity Identity -- | Write effect-ful stream processing functions and compose them into a -- series of tubes. -- -- This exists primarily for my own education. It is updated often as I -- try things and is probably, at this moment, wrong. -- -- If you want to know more about efficient stream processing: -- -- http://okmij.org/ftp/Streams.html -- -- My goals were to -- --
-- data TubeF a b k -- = Await (a -> k) -- :: (a -> k) -> TubeF a b k -- | Yield (b , k) -- :: (b , k) -> TubeF a b k -- ---- -- The type signatures for the two value constructors should bear a -- strong resemblance to the actual type signature of runT. -- Instead of encoding tubes as structures which build up when composed, -- a TubeF is a control flow mechanism which picks one of two -- provided continuations. -- -- People using this library should never have to contend with these -- details but it is worth mentioning. newtype TubeF a b k TubeF :: (forall r. ((a -> k) -> r) -> ((b, k) -> r) -> r) -> TubeF a b k runT :: TubeF a b k -> forall r. ((a -> k) -> r) -> ((b, k) -> r) -> r -- | A computation which only yields and never awaits type Source b m r = forall x. Tube x b m r -- | A computation which only awaits and never yields. type Sink a m r = forall x. Tube a x m r -- | A computation which neither yields nor awaits type Action m r = forall x. Tube x x m r -- | run is shorter than runFreeT and who knows, maybe it'll -- change some day run :: FreeT f m a -> m (FreeF f a (FreeT f m a)) -- | Command to wait for a new value upstream await :: Monad m => Tube a b m a -- | Command to send a value downstream yield :: Monad m => b -> Tube a b m () -- | Convert a list to a Source each :: (Monad m, Foldable t) => t b -> Tube a b m () -- | Enumerate yielded values into a continuation, creating a new -- Source for :: Monad m => Tube a b m r -> (b -> Tube a c m s) -> Tube a c m r -- | Infix version of for (~>) :: Monad m => Tube a b m r -> (b -> Tube a c m s) -> Tube a c m r -- | Connect a task to a continuation yielding another task; see -- >< (>-) :: Monad m => Tube a b m r -> (b -> Tube b c m r) -> Tube a c m r -- | Compose two tubes into a new tube. (><) :: Monad m => Tube a b m r -> Tube b c m r -> Tube a c m r -- | This performs a neat trick: a Tube with a return type -- a will be turned into a new Tube containing the -- underlying TubeF value. -- -- In this way the >< and >- functions can replace -- the () return value with a continuation and recursively -- traverse the computation until a final result is reached. liftT :: (MonadTrans t, Monad m) => FreeT f m a -> t m (FreeF f a (FreeT f m a)) -- | Continuously relays any values it receives. Iteratee identity. cat :: Monad m => Tube a a m r -- | Transforms all incoming values according to some function. map :: Monad m => (a -> b) -> Tube a b m r -- | Refuses to yield the first n values it receives. drop :: Monad m => Int -> Tube a a m r -- | Relay only the first n elements of a stream. take :: Monad m => Int -> Tube a a m () -- | Terminates the stream upon receiving a value violating the predicate takeWhile :: Monad m => (a -> Bool) -> Tube a a m () -- | Yields only values satisfying some predicate. filter :: Monad m => (a -> Bool) -> Tube a a m r -- | Strict left-fold of a stream. Note that the actual return type of the -- source is not relevant, only the intermediate yield type. reduce :: Monad m => (x -> a -> x) -> x -> (x -> b) -> Source a m () -> m b -- | Similar to each except it explicitly marks the stream as -- exhausted every :: (Foldable t, Monad m) => t b -> Tube a (Maybe b) m () -- | Taps the next value from a source, maybe. unyield :: Monad m => FreeT (TubeF x b) m () -> m (Maybe (b, FreeT (TubeF x b) m ())) -- | Source of Strings from stdin. This is mostly for debugging / -- ghci example purposes. prompt :: Source String IO () -- | Sink for Strings to stdout. This is mostly for debugging / ghci -- example purposes. display :: Sink String IO () -- | A Pump is the dual to a Tube: where a Tube is a -- computation manipulating a stream of values, a Pump can be -- situated on either end of a tube to both insert values when requested -- and handle any yielded results. -- -- This module is subject to change before I upload `0.2.0.0` to Hackage. type Pump a b = CofreeT (PumpF a b) data PumpF a b k PumpF :: (a, k) -> (b -> k) -> PumpF a b k recvF :: PumpF a b k -> (a, k) sendF :: PumpF a b k -> (b -> k) -- | Creates a Pump for a Tube using a comonadic seed value, -- a function to give it more data upon request, and a function to handle -- any yielded results. . Values received from the Tube may be -- altered and sent back into the tube, hence this mechanism does act -- like something of a pump. pump :: Comonad w => w a -> (w a -> (b, w a)) -> (w a -> c -> w a) -> Pump b c w a -- | Send a value into a Pump, effectively re-seeding the stream. send :: Comonad w => Pump a b w r -> b -> Pump a b w r -- | Pull a value from a Pump, along with the rest of the -- Pump. recv :: Comonad w => Pump a b w r -> (a, Pump a b w r) -- | Given a suitably matching Tube and Pump, you can use the -- latter to execute the former. runPump :: (Comonad w, Monad m) => (x -> y -> r) -> Pump a b w x -> Tube a b m y -> m r -- | Lift a computation from the argument monad to the constructed monad. lift :: MonadTrans t => forall (m :: * -> *) a. Monad m => m a -> t m a runFreeT :: FreeT f m a -> m (FreeF f a (FreeT f m a))