-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A simple effect system that integrates with MTL -- -- Please see README.md @package simple-effects @version 0.9.0.0 module Control.Monad.Runnable -- | A class of monads that have a run function. -- -- The runMonad function gives the result inside of IO. The only -- reason for this is to allow an instance for IO to be written. Other -- instances do not perform any aditional IO. -- -- Instances for Identity, IO and (Runnable m, -- RunnableTrans t, Monad (t m)) => Runnable (t -- m) are given so users should only provide additional -- RunnableTrans instances instead of Runnable ones. class Monad m => Runnable m where type MonadicState m :: * type MonadicResult m a :: * where { type family MonadicState m :: *; type family MonadicResult m a :: *; } -- | Get the current state value. currentMonadicState :: Runnable m => m (MonadicState m) -- | If given a result, reconstruct a monadic compitation. restoreMonadicState :: Runnable m => MonadicResult m a -> m a -- | Given the required state value and a computation, run the computation -- up to the IO effect. This should effectively run each layer in the -- transformer stack. The MonadicState should hold all the needed -- information to do so. -- -- A more formal description of what it means to run a transformer is -- given for the runTransformer function. runMonad :: Runnable m => MonadicState m -> m a -> IO (MonadicResult m a) -- | A class of transformers that can run their effects in the underlying -- monad. -- -- The following laws need to hold. -- --
-- t -> do st <- currentTransState -- res <- lift (runTransformer t st) -- restoreTransState res -- == id ---- --
-- f :: (forall a. m a -> m a) -- m s -> runTransformer (lift (f m)) s == m s -> f (runTransformer (lift m) s) --class MonadTrans t => RunnableTrans t where type TransformerState t (m :: * -> *) :: * type TransformerResult t (m :: * -> *) a :: * where { type family TransformerState t (m :: * -> *) :: *; type family TransformerResult t (m :: * -> *) a :: *; } -- | Get the current state value. currentTransState :: (RunnableTrans t, Monad m) => t m (TransformerState t m) -- | If given a result, reconstruct the compitation. restoreTransState :: (RunnableTrans t, Monad m) => TransformerResult t m a -> t m a -- | Given the required state value and a computation, run the effects of -- the transformer in the underlying monad. runTransformer :: (RunnableTrans t, Monad m) => t m a -> TransformerState t m -> m (TransformerResult t m a) instance Control.Monad.Runnable.Runnable Data.Functor.Identity.Identity instance Control.Monad.Runnable.Runnable GHC.Types.IO instance (Control.Monad.Runnable.Runnable m, Control.Monad.Runnable.RunnableTrans t, GHC.Base.Monad (t m)) => Control.Monad.Runnable.Runnable (t m) instance Control.Monad.Runnable.RunnableTrans (Control.Monad.Trans.State.Strict.StateT s) instance Control.Monad.Runnable.RunnableTrans (Control.Monad.Trans.State.Lazy.StateT s) instance GHC.Base.Monoid s => Control.Monad.Runnable.RunnableTrans (Control.Monad.Trans.Writer.Strict.WriterT s) instance GHC.Base.Monoid s => Control.Monad.Runnable.RunnableTrans (Control.Monad.Trans.Writer.Lazy.WriterT s) instance Control.Monad.Runnable.RunnableTrans (Control.Monad.Trans.Reader.ReaderT s) instance GHC.Base.Monoid w => Control.Monad.Runnable.RunnableTrans (Control.Monad.Trans.RWS.Strict.RWST r w s) instance GHC.Base.Monoid w => Control.Monad.Runnable.RunnableTrans (Control.Monad.Trans.RWS.Lazy.RWST r w s) instance Control.Monad.Runnable.RunnableTrans Control.Monad.Trans.Identity.IdentityT instance Control.Monad.Trans.Error.Error e => Control.Monad.Runnable.RunnableTrans (Control.Monad.Trans.Error.ErrorT e) instance Control.Monad.Runnable.RunnableTrans (Control.Monad.Trans.Except.ExceptT e) instance Control.Monad.Runnable.RunnableTrans Control.Monad.Trans.Maybe.MaybeT instance Control.Monad.Runnable.RunnableTrans ListT.ListT module Control.Effects data MsgOrRes Msg :: MsgOrRes Res :: MsgOrRes class Monad m => MonadEffect effKind m -- | Use the effect described by method. effect :: MonadEffect effKind m => Effect effKind method Msg -> m (Effect effKind method Res) newtype EffectWithKind effKind m EffectWithKind :: (forall method. Effect effKind method Msg -> m (Effect effKind method Res)) -> EffectWithKind effKind m [getEffectWithKind] :: EffectWithKind effKind m -> forall method. Effect effKind method Msg -> m (Effect effKind method Res) -- | The EffectHandler is really just a ReaderT carrying -- around the function that knows how to handle the effect. newtype EffectHandler effKind m a EffectHandler :: ReaderT (EffectWithKind effKind m) m a -> EffectHandler effKind m a [unpackEffectHandler] :: EffectHandler effKind m a -> ReaderT (EffectWithKind effKind m) m a -- | Handle the effect described by effKind. handleEffect :: (forall method. Effect effKind method Msg -> m (Effect effKind method Res)) -> EffectHandler effKind m a -> m a instance Control.Monad.Random.Class.MonadRandom m => Control.Monad.Random.Class.MonadRandom (Control.Effects.EffectHandler effKind m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Control.Effects.EffectHandler effKind m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Control.Effects.EffectHandler effKind m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Effects.EffectHandler effKind m) instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Control.Effects.EffectHandler effKind m) instance GHC.Base.Alternative m => GHC.Base.Alternative (Control.Effects.EffectHandler effKind m) instance GHC.Base.Monad m => GHC.Base.Monad (Control.Effects.EffectHandler effKind m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Control.Effects.EffectHandler effKind m) instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effects.EffectHandler effKind m) instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Control.Effects.EffectHandler effKind m) instance Control.Monad.Trans.Class.MonadTrans (Control.Effects.EffectHandler effKind) instance Control.Monad.Runnable.RunnableTrans (Control.Effects.EffectHandler effKind) instance Control.Monad.Reader.Class.MonadReader s m => Control.Monad.Reader.Class.MonadReader s (Control.Effects.EffectHandler effKind m) instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Control.Effects.EffectHandler effKind m) instance (Control.Effects.MonadEffect method m, Control.Monad.Trans.Class.MonadTrans t, GHC.Base.Monad (t m)) => Control.Effects.MonadEffect method (t m) instance GHC.Base.Monad m => Control.Effects.MonadEffect effKind (Control.Effects.EffectHandler effKind m) -- | A neat effect that you can use to get early returns in your functions. -- Here's how to use it. -- -- Before: -- --
-- f = do -- m1 <- maybeFunc1 -- case m1 of -- Nothing -> return "1 nothing" -- Just x -> do -- m2 <- maybeFunc2 -- case m2 of -- Nothing -> return "2 nothing" -- Just y -> return (x <> y) ---- -- After: -- --
-- f = handleEarly $ do -- m1 <- maybeFunc1 -- x <- ifNothingEarlyReturn "1 nothing" m1 -- m2 <- maybeFunc2 -- y <- ifNothingEarlyReturn "2 nothing" m2 -- return (x <> y) ---- -- You can use the earlyReturn function directily, or one of the -- helpers for common use cases. module Control.Effects.Early data Early a -- | Allows you to return early from a function. Make sure you -- handleEarly to get the actual result out. earlyReturn :: forall a b m. MonadEffect (Early a) m => a -> m b -- | Get the result from a computation. Either the early returned one, or -- the regular result. handleEarly :: Monad m => ExceptT (EarlyValue a) m a -> m a -- | Only do the given action and exit early with it's result. onlyDo :: MonadEffect (Early a) m => m a -> m b -- | Early return the given value if the Maybe is Nothing. -- Otherwise, contnue with the value inside of it. ifNothingEarlyReturn :: MonadEffect (Early a) m => a -> Maybe b -> m b -- | Only do the given action and early return with it's result if the -- given value is Nothing. Otherwise continue with the value -- inside of the Maybe. ifNothingDo :: MonadEffect (Early a) m => m a -> Maybe b -> m b -- | If the value is a Left, get the value, process it and early -- return the result. Otherwise just return the Right value. ifLeftEarlyReturn :: MonadEffect (Early c) m => (a -> c) -> Either a b -> m b -- | If the value is a Left, get the value, process it and only do -- the resulting action. Otherwise just return the Right value. ifLeftDo :: MonadEffect (Early c) m => (a -> m c) -> Either a b -> m b instance (GHC.Base.Monad m, a ~ b) => Control.Effects.MonadEffect (Control.Effects.Early.Early a) (Control.Monad.Trans.Except.ExceptT (Control.Effects.Early.EarlyValue b) m) -- | Add non-determinism to your monad. Uses the ListT transformer -- under the hood. module Control.Effects.List newtype NonDeterministic Choose :: Type -> NonDeterministic -- | Runs the rest of the computation for every value in the list choose :: MonadEffect NonDeterministic m => [a] -> m a -- | Signals that this branch of execution failed to produce a result. deadEnd :: MonadEffect NonDeterministic m => m a -- | Execute all the effects and collect the result in a list. Note that -- this forces all the results, no matter which elements of the result -- list you end up actually using. For lazyer behavior use the other -- handlers. evaluateToList :: Monad m => ListT m a -> m [a] -- | Given a function, apply it to all the results. traverseAllResults :: Monad m => (a -> m ()) -> ListT m a -> m () -- | Given a folding function, fold over every result. If you want to -- terminate eary, use the foldWithEarlyTermination instead. foldAllResults :: Monad m => (r -> a -> m r) -> r -> ListT m a -> m r -- | Same as foldAllResults but the folding function has the ability -- to terminate early by returning Nothing. foldWithEarlyTermination :: Monad m => (r -> a -> m (Maybe r)) -> r -> ListT m a -> m r -- | Executes only the effects needed to produce the first n results. evaluateNResults :: Monad m => Int -> ListT m a -> m [a] -- | Executes only the effects needed to produce a single result. evaluateOneResult :: Monad m => ListT m a -> m (Maybe a) instance GHC.Base.Monad m => Control.Effects.MonadEffect Control.Effects.List.NonDeterministic (ListT.ListT m) -- | The regular old MonadReader effect with some differences. -- First, there's no functional dependency limiting your stack to a -- single environment type. This means less type inference so it might -- not be enough to just write readEnv. Write 'readEnv @MyEnvType' -- instead using TypeApplications. -- -- Second, the function has a less generic name and is called -- readEnv. -- -- Third, since it's a part of this effect framework, you get a -- handleReadEnv function with which you can provide a different -- environment implementation _at runtime_. module Control.Effects.Reader data ReadEnv e ReadEnv :: ReadEnv e readEnv :: forall e m. MonadEffect (ReadEnv e) m => m e handleReadEnv :: Functor m => m e -> EffectHandler (ReadEnv e) m a -> m a handleSubreader :: MonadEffect (ReadEnv e) m => (e -> e') -> EffectHandler (ReadEnv e') m a -> m a -- | This effect allows you to "throw" a signal. For the most part signals -- are the same as checked exceptions. The difference here is that the -- handler has the option to provide the value that will be the result -- of calling the signal function. This effectively allows -- you to have recoverable exceptions at the throw site, instead of just -- at the handling site. module Control.Effects.Signal -- | The handle function will return a value of this type. data ResumeOrBreak b c -- | Give a value to the caller of signal and keep going. Resume :: b -> ResumeOrBreak b c -- | Continue the execution after the handler. The handler will return this -- value Break :: c -> ResumeOrBreak b c data Signal a b -- | Throw a signal with no possible recovery. The handler is forced to -- only return the Break constructor because it cannot construct a -- Void value. -- -- If this function is used along with handleAsException, this -- module behaves like regular checked exceptions. throwSignal :: Throws a m => a -> m b -- | Handle signals of a computation. The handler function has the option -- to provide a value to the caller of signal and continue -- execution there, or do what regular exception handlers do and continue -- execution after the handler. handleSignal :: forall a b c m. Monad m => (a -> m (ResumeOrBreak b c)) -> EffectHandler (Signal a b) (ExceptT c m) c -> m c type Throws e m = MonadEffect (Signal e Void) m -- | This handler can only behave like a regular exception handler. If used -- along with throwSignal this module behaves like regular checked -- exceptions. handleException :: Monad m => (a -> m c) -> ExceptT a m c -> m c -- | See documentation for handleException. This handler gives you -- an Either. handleToEither :: ExceptT e m a -> m (Either e a) -- | The parameterizable maybe monad, obtained by composing an arbitrary -- monad with the Maybe monad. -- -- Computations are actions that may produce a value or exit. -- -- The return function yields a computation that produces that -- value, while >>= sequences two subcomputations, exiting -- if either computation does. newtype MaybeT (m :: * -> *) a :: (* -> *) -> * -> * MaybeT :: m (Maybe a) -> MaybeT a [runMaybeT] :: MaybeT a -> m (Maybe a) -- | Discard all the Throws and Signal constraints. If any -- exception was thrown the result will be Nothing. discardAllExceptions :: MaybeT m a -> m (Maybe a) -- | Satisfies all the Throws and Signal constraints -- if they all throw Showable exceptions. The first thrown -- exception will be shown and returned as a Left result. showAllExceptions :: Functor m => ExceptT SomeSignal m a -> m (Either Text a) -- | A class of monads that throw and catch exceptions of type e. -- An overlappable instance is given so you just need to make sure your -- transformers have a RunnableTrans instance. class Throws e m => Handles e m -- | Use this function to handle exceptions without discarding the -- Throws constraint. You'll want to use this if you're writing a -- recursive function. Using the regular handlers in that case will -- result with infinite types. -- -- Since this function doesn't discard constraints, you still need to -- handle the whole thing. -- -- Here's a slightly contrived example. -- --
-- data NotFound = NotFound -- data Tree a = Leaf a | Node (Tree a) (Tree a) -- data Step = GoLeft | GoRight -- findIndex :: (Handles NotFound m, Eq a) => a -> Tree a -> m [Step] -- findIndex x (Leaf a) | x == a = return [] -- | otherwise = throwSignal NotFound -- findIndex x (Node l r) = ((GoLeft :) $ findIndex x l) -- & handleRecursive (NotFound -> (GoRight :) $ findIndex x r) ---- -- Note: When you finally handle the exception effect, the order in which -- you handle it and other effects determines whether -- handleRecursive rolls back other effects if an exception -- occured or it preserves all of them up to the point of the exception. -- Handling exceptions last and handling them first will produce the -- former and latter behaviour respectively. handleRecursive :: Handles e m => (e -> m a) -> m a -> m a -- | handleToEither that doesn't discard Throws constraints. -- See documentation for handleRecursive. handleToEitherRecursive :: Handles e m => m a -> m (Either e a) data SomeSignal signal :: MonadEffect (Signal a b) m => a -> m b instance GHC.Show.Show Control.Effects.Signal.SomeSignal instance GHC.Read.Read Control.Effects.Signal.SomeSignal instance GHC.Classes.Ord Control.Effects.Signal.SomeSignal instance GHC.Classes.Eq Control.Effects.Signal.SomeSignal instance GHC.Base.Monad m => Control.Effects.MonadEffect (Control.Effects.Signal.Signal e b) (Control.Monad.Trans.Except.ExceptT e m) instance (GHC.Show.Show e, GHC.Base.Monad m) => Control.Effects.MonadEffect (Control.Effects.Signal.Signal e b) (Control.Monad.Trans.Except.ExceptT Control.Effects.Signal.SomeSignal m) instance GHC.Base.Monad m => Control.Effects.MonadEffect (Control.Effects.Signal.Signal a b) (Control.Monad.Trans.Maybe.MaybeT m) instance (TypeError ...) => Control.Effects.MonadEffect (Control.Effects.Signal.Signal a b) GHC.Types.IO instance (GHC.Base.Monad m, b ~ c) => Control.Effects.MonadEffect (Control.Effects.Signal.Signal a c) (Control.Effects.EffectHandler (Control.Effects.Signal.Signal a b) m) instance GHC.Base.Monad m => Control.Effects.Signal.Handles e (Control.Monad.Trans.Except.ExceptT e m) instance (GHC.Base.Monad m, GHC.Base.Monad (t m), Control.Effects.Signal.Handles e m, Control.Monad.Runnable.RunnableTrans t) => Control.Effects.Signal.Handles e (t m) -- | The MonadState you know and love with some differences. First, -- there's no functional dependency limiting your stack to a single state -- type. This means less type inference so it might not be enough to just -- write getState. Write 'getState @MyStateType' instead using -- TypeApplications. -- -- Second, the functions have less generic names and are called -- getState and setState. -- -- Third, since it's a part of this effect framework, you get a -- handleState function with which you can provide a different -- state implementation _at runtime_. module Control.Effects.State data State s Get :: State s Set :: State s getState :: forall s m. MonadEffect (State s) m => m s setState :: forall s m. MonadEffect (State s) m => s -> m () modifyState :: forall s m. MonadEffect (State s) m => (s -> s) -> m () -- | Handle the 'MonadEffect (State s)' constraint by providing custom -- handling functions. handleState :: forall m s a. Monad m => m s -> (s -> m ()) -> EffectHandler (State s) m a -> m a -- | Handle the state requirement using an IORef. handleStateIO :: MonadIO m => s -> EffectHandler (State s) m a -> m a -- | Handle the state requirement using the standard StateT -- transformer. handleStateT :: Monad m => s -> StateT s m a -> m a instance GHC.Base.Monad m => Control.Effects.MonadEffect (Control.Effects.State.State s) (Control.Monad.Trans.State.Lazy.StateT s m) module Control.Effects.Parallel forkThread :: IO () -> IO (MVar ()) appendState :: forall s m a proxy. (Semigroup s, MonadEffect (State s) m) => proxy s -> m a -> m a parallelWithRestore :: forall m a. Runnable m => (m a -> m a) -> [m a] -> m [a] parallelWithSequence :: Runnable m => [m a] -> m [a] parallel :: forall m a. Runnable m => [m a] -> m [MonadicResult m a]