-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | boxes -- -- concurrent, effectful boxes @package box @version 0.6.2 -- | commit module Box.Committer -- | a Committer a "commits" values of type a. A Sink and a Consumer are -- some other metaphors for this. -- -- A Committer absorbs the value being committed; the value disappears -- into the opaque thing that is a Committer from the pov of usage. newtype Committer m a Committer :: (a -> m Bool) -> Committer m a [commit] :: Committer m a -> a -> m Bool -- | Do nothing with values that are committed. -- -- This is useful for keeping the commit end of a box or pipeline open. drain :: Applicative m => Committer m a -- | This is a contramapMaybe, if such a thing existed, as the -- contravariant version of a mapMaybe. See witherable mapC :: Monad m => (b -> m (Maybe a)) -> Committer m a -> Committer m b -- | adds a monadic action to the committer premapC :: Applicative m => (Committer m a -> m ()) -> Committer m a -> Committer m a -- | adds a post-commit monadic action to the committer postmapC :: Monad m => (Committer m a -> m ()) -> Committer m a -> Committer m a -- | commit to a StateT list stateC :: Monad m => Committer (StateT [a] m) a -- | list committer listC :: Monad m => Committer m a -> Committer m [a] instance Control.Monad.Morph.MFunctor Box.Committer.Committer instance GHC.Base.Applicative m => GHC.Base.Semigroup (Box.Committer.Committer m a) instance GHC.Base.Applicative m => GHC.Base.Monoid (Box.Committer.Committer m a) instance Data.Functor.Contravariant.Contravariant (Box.Committer.Committer m) instance GHC.Base.Applicative m => Data.Functor.Contravariant.Divisible.Divisible (Box.Committer.Committer m) instance GHC.Base.Applicative m => Data.Functor.Contravariant.Divisible.Decidable (Box.Committer.Committer m) -- | A continuation type. module Box.Cont -- | A continuation similar to ` Control.Monad.ContT` but where the result -- type is swallowed by an existential newtype Cont m a Cont :: (forall r. (a -> m r) -> m r) -> Cont m a [with] :: Cont m a -> forall r. (a -> m r) -> m r -- | finally run a continuation runCont :: Cont m (m r) -> m r -- | fmap over a continuation and then run the result. -- -- The . position is towards the continuation (<$.>) :: (a -> m r) -> Cont m a -> m r infixr 3 <$.> -- | fmap over a continuation and then run the result. -- -- The . position is towards the continuation (<*.>) :: Cont m (a -> m r) -> Cont m a -> m r infixr 3 <*.> -- | sometimes you have no choice but to void it up newtype Cont_ m a Cont_ :: ((a -> m ()) -> m ()) -> Cont_ m a [with_] :: Cont_ m a -> (a -> m ()) -> m () -- | finally run a Cont_ runCont_ :: Cont_ m (m ()) -> m () instance GHC.Base.Functor (Box.Cont.Cont_ m) instance GHC.Base.Applicative (Box.Cont.Cont_ m) instance GHC.Base.Monad (Box.Cont.Cont_ m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Box.Cont.Cont_ m) instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Box.Cont.Cont_ m a) instance (GHC.Base.Functor m, GHC.Base.Semigroup a, GHC.Base.Monoid a) => GHC.Base.Monoid (Box.Cont.Cont_ m a) instance GHC.Base.Functor (Box.Cont.Cont m) instance GHC.Base.Applicative (Box.Cont.Cont m) instance GHC.Base.Monad (Box.Cont.Cont m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Box.Cont.Cont m) instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Box.Cont.Cont m a) instance (GHC.Base.Functor m, GHC.Base.Semigroup a, GHC.Base.Monoid a) => GHC.Base.Monoid (Box.Cont.Cont m a) -- | emit module Box.Emitter -- | an Emitter "emits" values of type a. A Source & a Producer -- (of a's) are the two other alternative but overloaded metaphors out -- there. -- -- An Emitter "reaches into itself" for the value to emit, where itself -- is an opaque thing from the pov of usage. An Emitter is named for its -- main action: it emits. newtype Emitter m a Emitter :: m (Maybe a) -> Emitter m a [emit] :: Emitter m a -> m (Maybe a) -- | like a monadic mapMaybe. (See witherable) mapE :: Monad m => (a -> m (Maybe b)) -> Emitter m a -> Emitter m b -- | read parse emitter, returning the original string on error readE :: (Functor m, Read a) => Emitter m Text -> Emitter m (Either Text a) -- | no error-reporting reading readE_ :: (Monad m, Read a) => Emitter m Text -> Emitter m a -- | parse emitter which returns the original text on failure parseE :: Functor m => Parser a -> Emitter m Text -> Emitter m (Either Text a) -- | no error-reporting parsing parseE_ :: Monad m => Parser a -> Emitter m Text -> Emitter m a -- | adds a pre-emit monadic action to the emitter premapE :: Applicative m => (Emitter m a -> m ()) -> Emitter m a -> Emitter m a -- | adds a post-emit monadic action to the emitter postmapE :: Monad m => (Emitter m a -> m ()) -> Emitter m a -> Emitter m a -- | add a post-emit monadic action on the emitted value (if there was any) postmapM :: Monad m => (a -> m ()) -> Emitter m a -> Emitter m a -- | turn an emitter into a list toListE :: Monad m => Emitter m a -> m [a] -- | convert a list emitter to a Stateful element emitter unlistE :: Monad m => Emitter m [a] -> Emitter (StateT [a] m) a -- | emit from a StateT list -- -- This compiles but is an infinite "a" emitter: -- -- let e1 = hoist (flip evalStateT ["a", "b"::Text]) stateE :: Emitter IO -- Text stateE :: Monad m => Emitter (StateT [a] m) a takeE :: Monad m => Int -> Emitter m a -> Emitter (StateT Int m) a -- | Take from an emitter until predicate takeUntilE :: Monad m => (a -> Bool) -> Emitter m a -> Emitter m a -- | Filter emissions according to a predicate. filterE :: Monad m => (a -> Bool) -> Emitter m a -> Emitter m a instance Control.Monad.Morph.MFunctor Box.Emitter.Emitter instance GHC.Base.Functor m => GHC.Base.Functor (Box.Emitter.Emitter m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Box.Emitter.Emitter m) instance GHC.Base.Monad m => GHC.Base.Monad (Box.Emitter.Emitter m) instance (GHC.Base.Monad m, GHC.Base.Alternative m) => GHC.Base.Alternative (Box.Emitter.Emitter m) instance (GHC.Base.Alternative m, GHC.Base.Monad m) => GHC.Base.MonadPlus (Box.Emitter.Emitter m) instance (GHC.Base.Alternative m, GHC.Base.Monad m) => GHC.Base.Semigroup (Box.Emitter.Emitter m a) instance (GHC.Base.Alternative m, GHC.Base.Monad m) => GHC.Base.Monoid (Box.Emitter.Emitter m a) -- | A box is something that commits and emits module Box.Box -- | A Box is a product of a Committer m and an Emitter. Think of a box -- with an incoming wire and an outgoing wire. Now notice that the -- abstraction is reversable: are you looking at two wires from "inside a -- box"; a blind erlang grunt communicating with the outside world via -- the two thin wires, or are you looking from "outside the box"; -- interacting with a black box object. Either way, it's a box. And -- either way, the committer is contravariant and the emitter covariant -- so it forms a profunctor. -- -- a Box can also be seen as having an input tape and output tape, thus -- available for turing and finite-state machine metaphorics. data Box m c e Box :: Committer m c -> Emitter m e -> Box m c e [committer] :: Box m c e -> Committer m c [emitter] :: Box m c e -> Emitter m e -- | a profunctor dimapMaybe bmap :: Monad m => (a' -> m (Maybe a)) -> (b -> m (Maybe b')) -> Box m a b -> Box m a' b' -- | Wrong signature for the MFunctor class hoistb :: Monad m => (forall a. m a -> n a) -> Box m c e -> Box n c e -- | Connect an emitter directly to a committer of the same type. -- -- The monadic action returns when the committer finishes. glue :: Monad m => Committer m a -> Emitter m a -> m () -- | Connect an emitter directly to a committer of the same type. -- -- The monadic action returns if the committer returns False. glue_ :: Monad m => Committer m a -> Emitter m a -> m () -- | Short-circuit a homophonuos box. glueb :: Monad m => Box m a a -> m () -- | fuse a box -- --
--   fuse (pure . pure) == glueb 
--   
fuse :: Monad m => (a -> m (Maybe b)) -> Box m b a -> m () -- | composition of monadic boxes dotb :: Monad m => Box m a b -> Box m b c -> m (Box m a c) class Divap p divap :: Divap p => (a -> (b, c)) -> ((d, e) -> f) -> p b d -> p c e -> p a f conpur :: Divap p => a -> p b a class Profunctor p => DecAlt p choice :: DecAlt p => (a -> Either b c) -> (Either d e -> f) -> p b d -> p c e -> p a f loss :: DecAlt p => p Void b instance (GHC.Base.Monad m, GHC.Base.Alternative m) => Box.Box.DecAlt (Box.Box.Box m) instance GHC.Base.Applicative m => Box.Box.Divap (Box.Box.Box m) instance GHC.Base.Functor m => Data.Profunctor.Unsafe.Profunctor (Box.Box.Box m) instance (GHC.Base.Alternative m, GHC.Base.Monad m) => GHC.Base.Semigroup (Box.Box.Box m c e) instance (GHC.Base.Alternative m, GHC.Base.Monad m) => GHC.Base.Monoid (Box.Box.Box m c e) -- | queues Follows pipes-concurrency module Box.Queue -- | Queue specifies how messages are queued data Queue a Unbounded :: Queue a Bounded :: Int -> Queue a Single :: Queue a Latest :: a -> Queue a Newest :: Int -> Queue a New :: Queue a -- | create an unbounded queue, returning the emitter result queueC :: MonadConc m => (Committer m a -> m l) -> (Emitter m a -> m r) -> m l -- | create an unbounded queue, returning the emitter result queueE :: MonadConc m => (Committer m a -> m l) -> (Emitter m a -> m r) -> m r -- | wait for the first action, and then cancel the second waitCancel :: MonadConc m => m b -> m a -> m b -- | create a queue, returning the ends ends :: MonadSTM stm => Queue a -> stm (a -> stm (), stm a) -- | connect a committer and emitter action via spawning a queue, and wait -- for both to complete. withQE :: MonadConc m => Queue a -> (Queue a -> m (Box m a a, m ())) -> (Committer m a -> m l) -> (Emitter m a -> m r) -> m r -- | connect a committer and emitter action via spawning a queue, and wait -- for both to complete. withQC :: MonadConc m => Queue a -> (Queue a -> m (Box m a a, m ())) -> (Committer m a -> m l) -> (Emitter m a -> m r) -> m l -- | turn a queue into a box (and a seal) toBox :: MonadSTM stm => Queue a -> stm (Box stm a a, stm ()) -- | turn a queue into a box (and a seal), and lift from stm to the -- underlying monad. toBoxM :: MonadConc m => Queue a -> m (Box m a a, m ()) -- | lift a box from STM liftB :: MonadConc m => Box (STM m) a b -> Box m a b -- | run two actions concurrently, but wait and return on the left result. concurrentlyLeft :: MonadConc m => m a -> m b -> m a -- | run two actions concurrently, but wait and return on the right result. concurrentlyRight :: MonadConc m => m a -> m b -> m b -- | turn a box action into a box continuation fromAction :: MonadConc m => (Box m a b -> m r) -> Cont m (Box m b a) -- | connect up two box actions via two queues fuseActions :: MonadConc m => (Box m a b -> m r) -> (Box m b a -> m r') -> m r' -- | various ways to connect things up module Box.Connectors -- | Turn a list into an Emitter continuation via a Queue fromListE :: MonadConc m => [a] -> Cont m (Emitter m a) -- | fromList_ directly supplies to a committer action -- -- FIXME: fromList_ combined with cRef is failing dejavu concurrency -- testing... fromList_ :: Monad m => [a] -> Committer m a -> m () -- | toList_ directly receives from an emitter -- -- TODO: check isomorphism -- --
--   toList_ == toListE
--   
toList_ :: Monad m => Emitter m a -> m [a] -- | take a list, emit it through a box, and output the committed result. -- -- The pure nature of this computation is highly useful for testing, -- especially where parts of the box under investigation has -- non-deterministic attributes. fromToList_ :: Monad m => [a] -> (Box (StateT ([b], [a]) m) b a -> StateT ([b], [a]) m r) -> m [b] -- | hook a committer action to a queue, creating an emitter continuation emitQ :: MonadConc m => (Committer m a -> m r) -> Cont m (Emitter m a) -- | hook a committer action to a queue, creating an emitter continuation commitQ :: MonadConc m => (Emitter m a -> m r) -> Cont m (Committer m a) -- | finite sink sink :: MonadConc m => Int -> (a -> m ()) -> Cont m (Committer m a) -- | finite source source :: MonadConc m => Int -> m a -> Cont m (Emitter m a) -- | glues an emitter to a committer, then resupplies the emitter forkEmit :: Monad m => Emitter m a -> Committer m a -> Emitter m a -- | a box modifier that feeds commits back to the emitter feedback :: MonadConc m => (a -> m (Maybe b)) -> Cont m (Box m b a) -> Cont m (Box m b a) -- | fuse a committer to a buffer queueCommitter :: MonadConc m => Committer m a -> Cont m (Committer m a) -- | fuse an emitter to a buffer queueEmitter :: MonadConc m => Emitter m a -> Cont m (Emitter m a) -- | concurrently run two emitters -- -- This differs from mappend in that the monoidal (and alternative) -- instance of an Emitter is left-biased (The left emitter exhausts -- before the right one is begun). This is non-deterministically -- concurrent. concurrentE :: MonadConc m => Emitter m a -> Emitter m a -> Cont m (Emitter m a) -- | run two committers concurrently concurrentC :: MonadConc m => Committer m a -> Committer m a -> Cont m (Committer m a) -- | Glues a committer and emitter, taking n emits -- --
--   >>> glueN 4 <$> pure (contramap show toStdout) <*.> fromListE [1..]
--   1
--   2
--   3
--   4
--   
glueN :: Monad m => Int -> Committer m a -> Emitter m a -> m () -- | IO actions module Box.IO -- | emit Text from stdin inputs -- --
--   >>> :t emit fromStdin
--   emit fromStdin :: IO (Maybe Text)
--   
fromStdin :: Emitter IO Text -- | commit to stdout -- --
--   >>> commit toStdout ("I'm committed!" :: Text)
--   I'm committed!
--   True
--   
toStdout :: Committer IO Text -- | finite console emitter fromStdinN :: Int -> Cont IO (Emitter IO Text) -- | finite console committer toStdoutN :: Int -> Cont IO (Committer IO Text) -- | read from console, throwing away read errors readStdin :: Read a => Emitter IO a -- | show to stdout showStdout :: Show a => Committer IO a -- | Emits lines of Text from a handle. handleE :: Handle -> Emitter IO Text -- | Commit lines of Text to a handle. handleC :: Handle -> Committer IO Text -- | commit to a list IORef cRef :: MonadConc m => m (Committer m a, m [a]) -- | emit from a list IORef eRef :: MonadConc m => [a] -> m (Emitter m a) -- | Emits lines of Text from a file. fileE :: FilePath -> Cont IO (Emitter IO Text) -- | Commits lines of Text to a file. fileWriteC :: FilePath -> Cont IO (Committer IO Text) -- | Commits lines of Text, appending to a file. fileAppendC :: FilePath -> Cont IO (Committer IO Text) -- | timing effects module Box.Time -- | sleep for x seconds sleep :: MonadConc m => Double -> m () -- | sleep until a certain time (in the future) sleepUntil :: UTCTime -> IO () -- | A value with a UTCTime annotation. data Stamped a Stamped :: UTCTime -> a -> Stamped a [stamp] :: Stamped a -> UTCTime [value] :: Stamped a -> a -- | Add the current time stampNow :: (MonadConc m, MonadIO m) => a -> m (LocalTime, a) -- | adding a time stamp stampE :: (MonadConc m, MonadIO m) => Emitter m a -> Emitter m (LocalTime, a) -- | wait until Stamped time before emitting emitOn :: Emitter IO (LocalTime, a) -> Emitter IO a -- | reset the emitter stamps to by in sync with the current time and -- adjust the speed >>> let e1 = fromListE (zipWith (x a -> -- Stamped (addUTCTime (fromDouble x) t) a) [0..5] [0..5]) playback :: Double -> Emitter IO (LocalTime, a) -> IO (Emitter IO (LocalTime, a)) -- | simulate a delay from a (Stamped a) Emitter relative to the first -- timestamp simulate :: Double -> Emitter IO (LocalTime, a) -> Cont IO (Emitter IO a) instance GHC.Read.Read a => GHC.Read.Read (Box.Time.Stamped a) instance GHC.Show.Show a => GHC.Show.Show (Box.Time.Stamped a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Box.Time.Stamped a) -- | Effectful, profunctor boxes designed for concurrency. -- -- This library follows the ideas and code from pipes-concurrency -- and mvc but with some polymorphic tweaks and definitively more -- pretentious names. module Box