-- 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.1.0.0 module Tubes.Core -- | A Tube is the free monad transformer arising from TubeF. type Tube a b m r = FreeT (TubeF a b) m r -- | TubeF is the union of unary functions and binary products into -- a single type, here defined with a Boehm-Berarducci encoding. -- -- Rather than using a normal ADT, which would certainly make the code a -- bit easier to read and write, a value of this type is actually a -- control flow mechanism accepting two continuations and choosing one or -- the other. -- -- Client code should never actually have to deal with this. 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 () -- | 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)) -- | 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 tasks in a pull-based stream (><) :: 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 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 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. unyield :: Monad m => Source b m () -> m (Maybe b) -- | 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 iteratees: -- -- http://okmij.org/ftp/Streams.html -- -- My goals were to (1) learn more about iteratees and (2) see how far I -- could get using free monads. module Tubes -- | TubeF is the union of unary functions and binary products into -- a single type, here defined with a Boehm-Berarducci encoding. -- -- Rather than using a normal ADT, which would certainly make the code a -- bit easier to read and write, a value of this type is actually a -- control flow mechanism accepting two continuations and choosing one or -- the other. -- -- Client code should never actually have to deal with this. 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 Tube is the free monad transformer arising from TubeF. type Tube a b m r = FreeT (TubeF a b) m 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 -- | 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)) -- | 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 () -- | Constructor for sink computations awaitF :: (a -> k) -> TubeF a b k -- | Constructor for source computations yieldF :: b -> k -> TubeF a b k -- | 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 tasks in a pull-based stream (><) :: Monad m => Tube a b m r -> Tube b c m r -> Tube a c 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)) -- | 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 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. unyield :: Monad m => Source b m () -> m (Maybe b) -- | 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 ()