-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A simple effect system that integrates with MTL -- -- Some of the things you can do with this package: -- -- -- --

Declare and check which side-effects your function uses

-- -- The library provides a nice, declarative way of specifying exactly -- what your monadic function does. -- --
--   getProductAndWriteToFile :: MonadEffects '[Database, FileSystem] m => ProductId -> FilePath -> m ()
--   
-- -- This way you can be sure that your harmlessFunction doesn't -- do unexpected things behind your back. The compiler makes sure that -- all the effects are accounted for in the function's type. -- --

Dependency injection

-- -- Functions are not tied to any specific implementation of an effect -- meaning you can swap out different implementations without changing -- your code. Code like this -- --
--   myFunction :: MonadEffects '[Time, Logging] m => m ()
--   myFunction = do
--       t <- getCurrentTime
--       log (show t)
--   
-- -- is effectively the same as -- --
--   myFunction :: Monad m => m ZonedTime -> (String -> m ()) -> m ()
--   myFunction getCurrentTime log = do
--       t <- getCurrentTime
--       log (show t)
--   
-- -- but the library does all the parameter passing for you. And just like -- you'd be able to provide any implementation as getCurrentTime -- and log parameters you can do the same with simple effects. -- --
--   myFunction
--       & implement (TimeMethods someCurrentTimeImplementation)
--       & implement (LoggingMethods someLoggingImplementation)
--   
-- --

Test effectful code

-- -- Easily provide dummy implementations of your effects to prevent -- missle-launching during testing. -- --
--   myEffectfulFunction :: MonadEffects '[Database, Missiles] m => m Int
--   
--   main = do
--       conn <- connectToDb "connStr"
--       myEffectfulFunction
--           & implement (realDatabase conn)
--           & implement (MissilesMethods (launchMissles "access codes"))
--   
--   spec = do
--       res <- myEffectfulFunction
--           & implement (fakeDb Map.empty)
--           & implement (MissilesMethods (print "Totally launching missiles"))
--       when (res /= 42) (error "Test failed!")
--   
-- --

Avoid the <math> instance problem

-- -- Any effect you define is automatically liftable through any -- transformer. Most MonadX instances you'd write would look -- like func a b c = lift (func a b c), so why would you have to -- write them yourself? simple-effects does it for you using an -- overlappable instance. -- -- What about effects that aren't that simple? Each effect can specify a -- constraint on the transformers that it can be lifted through and a -- mechanism that does the lifting. So you get all the benefits of -- automatic lifting of simple effects and retain all of the flexibility -- of complex ones. -- --

Define custom effects with very little programming overhead

-- -- Lets say we need a way to get coordinates for some address. Here's how -- we'd declare that functionality. -- --
--   data Geolocation m = GeolocationMethods
--       { _getLocation :: Address -> m Coordinates }
--       deriving (Generic, Effect)
--   getLocation :: MonadEffect Geolocation m => Address -> m Coordinates
--   getLocation = _getLocation effect
--   
-- -- That's all you need to start using your effect in functions. -- --
--   getUsersLocation :: (MonadEffect Geolocation m, MonadIO m) => m Coordinates
--   getUsersLocation = do
--       liftIO $ putStrLn "Please enter your address:"
--       addr <- liftIO readLn
--       getLocation addr
--   
-- --

Check out the tutorial modules for more details

@package simple-effects @version 0.13.0.0 module Control.Effects.Generic class (Generic (a m), Generic (a (t m)), SimpleMethodsRep (Rep (a m)) (Rep (a (t m))) m t) => SimpleMethods a (m :: * -> *) (t :: (* -> *) -> * -> *) liftSimple :: SimpleMethods a m t => a m -> a (t m) class SimpleMethodsRep r r' (m :: * -> *) (t :: (* -> *) -> * -> *) liftSimpleRep :: SimpleMethodsRep r r' m t => r x -> r' x class SimpleMethod f ft (m :: * -> *) (t :: (* -> *) -> * -> *) liftMethod :: SimpleMethod f ft m t => f -> ft genericLiftThrough :: forall t e m. (MonadTrans t, Monad m, Monad (t m), SimpleMethods e m t) => e m -> e (t m) class (Generic (a m), MonadicMethodsRep (Rep (a m)) m, Monad m) => MonadicMethods a m mergeMonadicMethods :: MonadicMethods a m => m (a m) -> a m class MonadicMethodsRep r m mergeMonadicMethodsRep :: MonadicMethodsRep r m => m (r x) -> r x class MonadicMethod a m mergeMonadicMethod :: MonadicMethod a m => m a -> a genericMergeContext :: MonadicMethods a m => m (a m) -> a m class ForceError (x :: *) instance Control.Effects.Generic.ForceError (TypeError ...) => Control.Effects.Generic.SimpleMethod (a -> f) (a' -> ft) m t instance Control.Effects.Generic.ForceError (TypeError ...) => Control.Effects.Generic.SimpleMethod a b m t instance Control.Effects.Generic.ForceError (TypeError ...) => Control.Effects.Generic.MonadicMethodsRep (a GHC.Generics.:+: b) m instance Control.Effects.Generic.ForceError (TypeError ...) => Control.Effects.Generic.MonadicMethodsRep GHC.Generics.V1 m instance Control.Effects.Generic.ForceError (TypeError ...) => Control.Effects.Generic.MonadicMethod a m instance (Control.Effects.Generic.MonadicMethod a m, GHC.Base.Functor m) => Control.Effects.Generic.MonadicMethodsRep (GHC.Generics.K1 x a) m instance (Control.Effects.Generic.MonadicMethod b m, GHC.Base.Functor m) => Control.Effects.Generic.MonadicMethod (a -> b) m instance GHC.Base.Monad m => Control.Effects.Generic.MonadicMethod (m a) m instance (GHC.Generics.Generic (a m), Control.Effects.Generic.MonadicMethodsRep (GHC.Generics.Rep (a m)) m, GHC.Base.Monad m) => Control.Effects.Generic.MonadicMethods a m instance (Control.Effects.Generic.MonadicMethodsRep c m, GHC.Base.Functor m) => Control.Effects.Generic.MonadicMethodsRep (GHC.Generics.M1 a b c) m instance (Control.Effects.Generic.MonadicMethodsRep a m, Control.Effects.Generic.MonadicMethodsRep b m, GHC.Base.Functor m) => Control.Effects.Generic.MonadicMethodsRep (a GHC.Generics.:*: b) m instance Control.Effects.Generic.MonadicMethodsRep GHC.Generics.U1 m instance Control.Effects.Generic.SimpleMethod a a' m t => Control.Effects.Generic.SimpleMethodsRep (GHC.Generics.K1 x a) (GHC.Generics.K1 x a') m t instance Control.Effects.Generic.SimpleMethod f ft m t => Control.Effects.Generic.SimpleMethod (a -> f) (a -> ft) m t instance (Control.Monad.Trans.Class.MonadTrans t, GHC.Base.Monad m) => Control.Effects.Generic.SimpleMethod (m a) (t m a) m t instance (GHC.Generics.Generic (a m), GHC.Generics.Generic (a (t m)), Control.Effects.Generic.SimpleMethodsRep (GHC.Generics.Rep (a m)) (GHC.Generics.Rep (a (t m))) m t) => Control.Effects.Generic.SimpleMethods a m t instance Control.Effects.Generic.SimpleMethodsRep c c' m t => Control.Effects.Generic.SimpleMethodsRep (GHC.Generics.M1 a b c) (GHC.Generics.M1 a b c') m t instance (Control.Effects.Generic.SimpleMethodsRep a a' m t, Control.Effects.Generic.SimpleMethodsRep b b' m t) => Control.Effects.Generic.SimpleMethodsRep (a GHC.Generics.:*: b) (a' GHC.Generics.:*: b') m t instance (Control.Effects.Generic.SimpleMethodsRep a a' m t, Control.Effects.Generic.SimpleMethodsRep b b' m t) => Control.Effects.Generic.SimpleMethodsRep (a GHC.Generics.:+: b) (a' GHC.Generics.:+: b') m t instance Control.Effects.Generic.SimpleMethodsRep GHC.Generics.U1 GHC.Generics.U1 m t instance Control.Effects.Generic.SimpleMethodsRep GHC.Generics.V1 GHC.Generics.V1 m t 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 { -- | The type of value that needs to be provided to run this monad. type family MonadicState m :: *; -- | The type of the result you get when you run this monad. 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) -- | 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, PureRunnable m) => MonadicState m -> m a -> IO (MonadicResult m a) class Runnable m => PureRunnable m runPureMonad :: PureRunnable m => MonadicState m -> m a -> MonadicResult m a -- | A class of transformers that can run their effects in the underlying -- monad. -- -- The following laws need to hold: -- -- class MonadTrans t => RunnableTrans t where { -- | The type of value that needs to be provided to run this transformer. type family TransformerState t (m :: * -> *) :: *; -- | The type of the result you get when you run this transformer. type family TransformerResult t a :: *; } -- | Get the current state value. currentTransState :: (RunnableTrans t, Monad m) => t m (TransformerState t m) -- | Given a result, interpret it as a computation. This restores the state -- of the transformer. restoreTransState :: (RunnableTrans t, Monad m) => TransformerResult t 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 a) 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.PureRunnable m, Control.Monad.Runnable.RunnableTrans t, GHC.Base.Monad (t m)) => Control.Monad.Runnable.PureRunnable (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 instance Control.Monad.Runnable.Runnable Data.Functor.Identity.Identity instance Control.Monad.Runnable.PureRunnable Data.Functor.Identity.Identity instance Control.Monad.Runnable.Runnable GHC.Types.IO module Control.Effects class UniqueEffect (effName :: k) (m :: * -> *) a | effName m -> a type family MonadEffects effs m :: Constraint newtype RuntimeImplemented e m a RuntimeImplemented :: ReaderT (e m) m a -> RuntimeImplemented e m a [getRuntimeImplemented] :: RuntimeImplemented e m a -> ReaderT (e m) m a class (Effect e, Monad m, ExtraConstraint e m) => MonadEffect e m effect :: MonadEffect e m => e m effect :: (MonadEffect e m, MonadEffect e m', Monad (t m'), CanLift e t, t m' ~ m) => e m class Effect (e :: (* -> *) -> *) where { type family CanLift e (t :: (* -> *) -> * -> *) :: Constraint; type family ExtraConstraint e (m :: * -> *) :: Constraint; type CanLift e t = MonadTrans t; type ExtraConstraint e m = (); } liftThrough :: forall t m. (Effect e, CanLift e t, Monad m, Monad (t m)) => e m -> e (t m) liftThrough :: forall t m. (Effect e, Generic (e m), MonadTrans t, Monad m, Monad (t m), SimpleMethods e m t) => e m -> e (t m) mergeContext :: (Effect e, Monad m) => m (e m) -> e m mergeContext :: (Effect e, Generic (e m), MonadicMethods e m) => m (e m) -> e m implement :: forall e m a. e m -> RuntimeImplemented e m a -> m a instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Control.Effects.RuntimeImplemented e m) instance Control.Monad.Random.Class.MonadRandom m => Control.Monad.Random.Class.MonadRandom (Control.Effects.RuntimeImplemented e m) instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Control.Effects.RuntimeImplemented e m) instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Control.Effects.RuntimeImplemented e m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Control.Effects.RuntimeImplemented e m) instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (Control.Effects.RuntimeImplemented e m) instance GHC.Base.Alternative m => GHC.Base.Alternative (Control.Effects.RuntimeImplemented e m) instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (Control.Effects.RuntimeImplemented e m) instance GHC.Base.Monad m => GHC.Base.Monad (Control.Effects.RuntimeImplemented e m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Control.Effects.RuntimeImplemented e m) instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effects.RuntimeImplemented e m) instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Control.Effects.RuntimeImplemented e m) instance forall k1 k2 (effName :: k2) (m :: * -> *) (a :: k1) (t :: (* -> *) -> * -> *). Control.Effects.UniqueEffect effName m a => Control.Effects.UniqueEffect effName (t m) a instance Control.Monad.Trans.Class.MonadTrans (Control.Effects.RuntimeImplemented e) instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (Control.Effects.RuntimeImplemented e m) instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Control.Effects.RuntimeImplemented e m) instance Control.Monad.Runnable.RunnableTrans (Control.Effects.RuntimeImplemented e) instance (Control.Effects.Effect e, GHC.Base.Monad m, Control.Effects.CanLift e (Control.Effects.RuntimeImplemented e), Control.Effects.ExtraConstraint e (Control.Effects.RuntimeImplemented e m)) => Control.Effects.MonadEffect e (Control.Effects.RuntimeImplemented e m) instance (Control.Effects.MonadEffect e m, GHC.Base.Monad (t m), Control.Effects.CanLift e t, Control.Effects.ExtraConstraint e (t m)) => Control.Effects.MonadEffect 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 an -- implement function with which you can provide a different state -- implementation at runtime. module Control.Effects.State data State s m StateMethods :: m s -> (s -> m ()) -> State s m [_getState] :: State s m -> m s [_setState] :: State s m -> s -> m () -- | Get current value of the state with the type s. You can use -- type applications to tell the type checker which type of state you -- want. getState @Int getState :: forall s m. MonadEffect (State s) m => m s -- | Set a new value for the state of type s You can use type -- applications to tell the type checker which type of state you're -- setting. setState @Int 5 setState :: forall s m. MonadEffect (State s) m => s -> m () -- | Transform the state of type s using the given function. You -- can use type applications to tell the type checker which type of state -- you're modifying. modifyState @Int (+ 1) modifyState :: forall s m. MonadEffect (State s) m => (s -> s) -> m () -- | Implement the state effect via the StateT transformer. If you have a -- function with a type like f :: MonadEffect (State Int) m => m -- () you can use implementStateViaStateT to satisfy the -- MonadEffect constraint. -- --
--   implementStateViaStateT @Int 0 f :: Monad m => m ()
--   
implementStateViaStateT :: forall s m a. Monad m => s -> StateT s m a -> m a -- | Handle the state requirement using an IORef. If you have a -- function with a type like f :: MonadEffect (State Int) m => m -- () you can use implementStateViaIORef to replace the -- MonadEffect constraint with MonadIO. This is convenient -- if you already have a MonadIO constraint and you don't want to -- use the StateT transformer for some reason. -- --
--   implementStateViaIORef @Int 0 f :: MonadIO m => m ()
--   
implementStateViaIORef :: forall s m a. MonadIO m => s -> RuntimeImplemented (State s) m a -> m a instance GHC.Generics.Generic (Control.Effects.State.State s m) instance Control.Effects.Effect (Control.Effects.State.State s) instance Control.Effects.UniqueEffect Control.Effects.State.State (Control.Monad.Trans.State.Lazy.StateT s m) s instance Control.Effects.UniqueEffect Control.Effects.State.State (Control.Effects.RuntimeImplemented (Control.Effects.State.State s) m) s instance GHC.Base.Monad m => Control.Effects.MonadEffect (Control.Effects.State.State s) (Control.Monad.Trans.State.Lazy.StateT s m) -- | 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 newtype Signal a b m SignalMethods :: (a -> m b) -> Signal a b m [_signal] :: Signal a b m -> a -> m 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 :: MonadEffect (Throw 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)) -> RuntimeImplemented (Signal a b) (ExceptT c m) c -> m c type Throw e = Signal e Void -- | This handler can only behave like a regular exception handler. If used -- along with throwSignal this module behaves like regular checked -- exceptions. handleException :: forall a c m. Monad m => (a -> m c) -> ExceptT a m c -> m c -- | See documentation for handleException. This handler gives you -- an Either. handleToEither :: forall e a m. 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 :: Type -> Type) a MaybeT :: m (Maybe a) -> MaybeT a [runMaybeT] :: MaybeT a -> m (Maybe a) -- | Discard all the Throw and Signal effects. If any -- exception was thrown the result will be Nothing. discardAllExceptions :: MaybeT m a -> m (Maybe a) -- | Satisfies all the Throw 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) newtype HandleException e m HandleExceptionMethods :: (forall a. (e -> m a) -> m a -> m a) -> HandleException e m [_handleWithoutDiscarding] :: HandleException e m -> forall a. (e -> m a) -> m a -> m a -- | Use this function to handle exceptions without discarding the -- Throw effect. 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 exception on the whole computation. -- -- 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)
--       & handleWithoutDiscarding (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 -- handleWithoutDiscarding 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. handleWithoutDiscarding :: forall e m a. MonadEffect (HandleException e) m => (e -> m a) -> m a -> m a -- | handleToEither that doesn't discard Throws -- constraints. See documentation for handleWithoutDiscarding. handleToEitherRecursive :: MonadEffect (HandleException e) m => m a -> m (Either e a) data SomeSignal signal :: forall a b m. 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.Generics.Generic (Control.Effects.Signal.Signal a b m) instance Control.Effects.Effect (Control.Effects.Signal.HandleException e) instance GHC.Base.Monad m => Control.Effects.MonadEffect (Control.Effects.Signal.HandleException e) (Control.Monad.Trans.Except.ExceptT e m) instance (TypeError ...) => Control.Effects.MonadEffect (Control.Effects.Signal.Signal a b) GHC.Types.IO 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 Control.Effects.Effect (Control.Effects.Signal.Signal a b) instance GHC.Base.Monad m => Control.Effects.MonadEffect (Control.Effects.Signal.Signal e b) (Control.Monad.Trans.Except.ExceptT e m) instance GHC.Base.Monad m => Control.Effects.MonadEffect (Control.Effects.Signal.Signal a b) (Control.Monad.Trans.Maybe.MaybeT m) instance (GHC.Base.Monad m, b Data.Type.Equality.~ c) => Control.Effects.MonadEffect (Control.Effects.Signal.Signal a c) (Control.Effects.RuntimeImplemented (Control.Effects.Signal.Signal a b) m) -- | Provides the Bracket effect for handing resource acquisition -- and safe cleanup. module Control.Effects.Resource -- | Class of transformers that don't introduce additional exit points to a -- computation. -- -- Examples: StateT s, ReaderT e, -- IdentityT -- -- Counter-examples: ExceptT e, ErrorT e, -- MaybeT, ListT class Unexceptional (t :: (* -> *) -> * -> *) newtype Bracket m BracketMethods :: (forall resource result cleanupRes. m resource -> (resource -> Maybe result -> m cleanupRes) -> (resource -> m result) -> m result) -> Bracket m [_bracket] :: Bracket m -> forall resource result cleanupRes. m resource -> (resource -> Maybe result -> m cleanupRes) -> (resource -> m result) -> m result -- | bracket acq cln use acquires the resource by running -- acq. If this computation aborts, the exception won't be -- handled and no cleanup will be performed since the resource wasn't -- acquired. Then use is called with the resource. Regardless if -- use threw an exception/aborted or finished normally, -- cln is called with the resource and possibly with the result -- of use (if it didn't abort). If there was an exception, it's -- rethrown: bracket is not meant to be used for exception handling. -- -- An exception in this context is anything from actual IO -- exceptions for pure ones "thrown" by ExceptT or MaybeT. -- In case of IO, the resource acquisition and cleanup are masked -- from async exceptions. -- -- Since this function can be used on almost any transformer stack, care -- needs to be taken that all the transformers that can throw -- exceptions get handled. This is why the effect isn't implicitly lifted -- through unknown transformers, only though ones that are instances of -- Unexceptional. If your transformer doesn't introduce new exit -- points, give it an instance of that class. There are no methods to -- implement. bracket :: MonadEffect Bracket m => m resource -> (resource -> Maybe result -> m cleanupRes) -> (resource -> m result) -> m result -- | A simpler version of bracket that doesn't use the results of -- the parameters. bracket_ :: MonadEffect Bracket m => m resource -> m cleanupRes -> m result -> m result type family UnexceptionalError (t :: (* -> *) -> * -> *) :: Constraint instance Control.Effects.Resource.UnexceptionalError t => Control.Effects.Resource.Unexceptional t instance Control.Effects.Effect Control.Effects.Resource.Bracket instance Control.Effects.MonadEffect Control.Effects.Resource.Bracket GHC.Types.IO instance Control.Effects.MonadEffect Control.Effects.Resource.Bracket Data.Functor.Identity.Identity instance Control.Effects.MonadEffect Control.Effects.Resource.Bracket m => Control.Effects.MonadEffect Control.Effects.Resource.Bracket (Control.Monad.Trans.Except.ExceptT e m) instance Control.Effects.MonadEffect Control.Effects.Resource.Bracket m => Control.Effects.MonadEffect Control.Effects.Resource.Bracket (Control.Monad.Trans.Maybe.MaybeT m) instance Control.Effects.Resource.Unexceptional (Control.Monad.Trans.State.Strict.StateT s) instance Control.Effects.Resource.Unexceptional (Control.Monad.Trans.State.Lazy.StateT s) instance Control.Effects.Resource.Unexceptional (Control.Monad.Trans.Writer.Strict.WriterT s) instance Control.Effects.Resource.Unexceptional (Control.Monad.Trans.Writer.Lazy.WriterT s) instance Control.Effects.Resource.Unexceptional (Control.Monad.Trans.RWS.Strict.RWST r w s) instance Control.Effects.Resource.Unexceptional (Control.Monad.Trans.RWS.Lazy.RWST r w s) instance Control.Effects.Resource.Unexceptional Control.Monad.Trans.Identity.IdentityT instance Control.Effects.Resource.Unexceptional (Control.Monad.Trans.Reader.ReaderT r) instance Control.Effects.Resource.Unexceptional (Control.Effects.RuntimeImplemented e) -- | 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 -- implementReadEnv function with which you can provide a -- different environment implementation _at runtime_. module Control.Effects.Reader newtype ReadEnv e m ReadEnvMethods :: m e -> ReadEnv e m [_readEnv] :: ReadEnv e m -> m e -- | Read a value of type e. Use with the TypeApplications -- extension to help with type inference readEnv @Int readEnv :: forall e m. MonadEffect (ReadEnv e) m => m e -- | Use the given action in the underlying monad to provide environment -- values. You can think of implementReadEnv x m as replacing -- all readEnv calls in m with x. implementReadEnv :: Functor m => m e -> RuntimeImplemented (ReadEnv e) m a -> m a instance GHC.Generics.Generic (Control.Effects.Reader.ReadEnv e m) instance Control.Effects.Effect (Control.Effects.Reader.ReadEnv e) -- | Sometimes it's useful to give a new name to an already existing -- effect. This module provides the tools to make that easy to do. module Control.Effects.Newtype -- | If we have a computation using some effect original, we can -- convert it into a computation that uses the effect newtyped -- instead. Provided, of course, that newtyped is really a -- newtype over the original effect. -- --
--   f :: MonadEffect (State Int) m => m ()
--   f = getState >>= i -> setState (i + 1)
--   
--   newtype MyState m = MyState (State Int m)
--   
--   -- inferred: g :: MonadEffect MyState m => m ()
--   g = effectAsNewtype @MyState @(State Int) f
--   
effectAsNewtype :: forall newtyped original m a. (MonadEffect newtyped m, Coercible (newtyped m) (original m)) => RuntimeImplemented original m a -> m a -- | A useful newtype for any effect. Just provide a unique tag, like a -- type level string. newtype EffTag (tag :: k) e (m :: * -> *) EffTag :: e m -> EffTag e -- | Rename an effect without explicitly declaring a new newtype. Just -- provide a tag. This is useful if you have two functions using the same -- effect that you want to combine but you don't want their effects to -- interact. For example, maybe they both work with Int states -- but you don't want them to modify each other's number. tagEffect :: forall tag original m a. MonadEffect (EffTag tag original) m => RuntimeImplemented original m a -> m a -- | Once you tag your effect, it's slightly inconvenient that you -- have to wrap your implementation when you want to handle it. This -- function doees the wrapping for you. -- --
--   f :: MonadEffect (State Int) m => m ()
--   f = getState >>= \s -> setState (s * 2)
--   
--   g :: MonadEffect (State Int) m => m ()
--   g = getState >>= \s -> setState (s * 3)
--   
--   combine :: Monad m => m Int
--   combine =
--       implementStateViaStateT 5 $ implementTagged @"s2" (StateMethods getState setState)
--       $ implementStateViaStateT 0 $ implementTagged @"s1" (StateMethods getState setState)
--       $ do
--       r1 <- tagEffect @"s1" @(State Int) (f >> getState)
--       r2 <- tagEffect @"s2" @(State Int) (g >> getState)
--       return (r1 + r2) -- results in 15
--   
implementTagged :: forall tag original m a. original m -> RuntimeImplemented (EffTag tag original) m a -> m a instance forall k (e :: (* -> *) -> *) (tag :: k). Control.Effects.Effect e => Control.Effects.Effect (Control.Effects.Newtype.EffTag tag e) instance forall k (e :: (* -> *) -> *) (e' :: (* -> *) -> *) (m :: * -> *) (tag :: k). (e Data.Type.Equality.~ e', Control.Effects.Effect e, GHC.Base.Monad m, Control.Effects.CanLift e (Control.Effects.RuntimeImplemented (Control.Effects.Newtype.EffTag tag e))) => Control.Effects.MonadEffect (Control.Effects.Newtype.EffTag tag e) (Control.Effects.RuntimeImplemented (Control.Effects.Newtype.EffTag tag e') m) -- | Add non-determinism to your monad. Uses the ListT transformer -- under the hood. module Control.Effects.List newtype NonDeterminism m NonDeterminismMethods :: (forall a. [a] -> m a) -> NonDeterminism m [_choose] :: NonDeterminism m -> forall a. [a] -> m a -- | Get a value from the list. The choice of which value to take is -- non-deterministic in a sense that the rest of the computation will be -- ran once for each of them. choose :: forall a m. MonadEffect NonDeterminism m => [a] -> m a -- | Signals that this branch of execution failed to produce a result. deadEnd :: MonadEffect NonDeterminism 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) -- | Execute all the effects but discard their results. evaluateAll :: Monad m => ListT m a -> m () -- | A transformation, which slices a list into chunks of the specified -- length. slice :: Monad m => Int -> ListT m a -> ListT m [a] -- | A transformation, reproducing the behaviour of -- Data.List.drop. drop :: Monad m => Int -> ListT m a -> ListT m a -- | A transformation, which traverses the stream with an action in the -- inner monad. traverse :: Monad m => (a -> m b) -> ListT m a -> ListT m b -- | Produce an infinite stream. repeat :: Monad m => a -> ListT m a -- | Construct by unfolding a monadic data structure -- -- This is the most memory-efficient way to construct ListT where the -- length depends on the inner monad. unfoldM :: Monad m => (b -> m (Maybe (a, b))) -> b -> ListT m a -- | Construct by unfolding a pure data structure. unfold :: Monad m => (b -> Maybe (a, b)) -> b -> ListT m a -- | Construct from an MVar, interpreting the value of Nothing as the end. fromMVar :: MonadIO m => MVar (Maybe a) -> ListT m a -- | Construct from any foldable. fromFoldable :: (Monad m, Foldable f) => f a -> ListT m a -- | Prepend an element. cons :: Monad m => a -> ListT m a -> ListT m a -- | Execute, consuming a list of the specified length and returning the -- remainder stream. splitAt :: Monad m => Int -> ListT m a -> m ([a], ListT m a) -- | Execute, traversing the stream with a side effect in the inner monad. traverse_ :: Monad m => (a -> m ()) -> ListT m a -> m () -- | Execute, folding to a list in the reverse order. Performs more -- efficiently than toList. toReverseList :: Monad m => ListT m a -> m [a] -- | Execute, folding to a list. toList :: Monad m => ListT m a -> m [a] -- | A version of fold, which allows early termination. foldMaybe :: Monad m => (r -> a -> m (Maybe r)) -> r -> ListT m a -> m r -- | Execute, applying a left fold. fold :: Monad m => (r -> a -> m r) -> r -> ListT m a -> m r -- | Execute, checking whether it's empty. null :: Monad m => ListT m a -> m Bool -- | Execute, getting the tail. Returns nothing if it's empty. tail :: Monad m => ListT m a -> m (Maybe (ListT m a)) -- | Execute, getting the head. Returns nothing if it's empty. head :: Monad m => ListT m a -> m (Maybe a) -- | Execute in the inner monad, getting the head and the tail. Returns -- nothing if it's empty. uncons :: () => ListT m a -> m (Maybe (a, ListT m a)) -- | A proper implementation of the list monad-transformer. Useful for -- streaming of monadic data structures. -- -- Since it has instances of MonadPlus and Alternative, you -- can use general utilities packages like "monadplus" with it. newtype ListT (m :: Type -> Type) a ListT :: m (Maybe (a, ListT m a)) -> ListT a instance Control.Effects.Effect Control.Effects.List.NonDeterminism instance GHC.Base.Monad m => Control.Effects.MonadEffect Control.Effects.List.NonDeterminism (ListT.ListT 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 directly, or one of the -- helpers for common use cases. module Control.Effects.Early newtype Early a m EarlyMethods :: (forall b. a -> m b) -> Early a m [_earlyReturn] :: Early a m -> forall b. a -> m b -- | 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 Control.Effects.Effect (Control.Effects.Early.Early a) instance (GHC.Base.Monad m, a Data.Type.Equality.~ b) => Control.Effects.MonadEffect (Control.Effects.Early.Early a) (Control.Monad.Trans.Except.ExceptT (Control.Effects.Early.EarlyValue b) m) -- | The Async effect allows you to fork new threads in monads other -- than just IO. module Control.Effects.Async data Async thread m AsyncMethods :: (forall a. m a -> m (thread m a)) -> (forall a. thread m a -> m a) -> (forall a n. thread n a -> m Bool) -> (forall a n. thread n a -> m ()) -> Async thread m [_async] :: Async thread m -> forall a. m a -> m (thread m a) [_waitAsync] :: Async thread m -> forall a. thread m a -> m a [_isAsyncDone] :: Async thread m -> forall a n. thread n a -> m Bool [_cancelAsync] :: Async thread m -> forall a n. thread n a -> m () class ThreadIdentifier thread mapThread :: ThreadIdentifier thread => (m a -> n b) -> thread m a -> thread n b -- | Fork a new thread to run the given computation. The monadic context is -- forked into the new thread. -- -- For example, if we use state, the current state value will be visible -- in the forked computation. Depending on how we ultimately implement -- the state, modifying it may or may not be visible from the main -- thread. If we use implementStateViaStateT then setting the -- state in the forked thread will just modify the thread-local value. On -- the other hand, if we use implementStateViaIORef then both -- the main thread and the new thread will use the same reference meaning -- they can interact through it. async :: MonadEffect (Async thread) m => m a -> m (thread m a) -- | Wait for the thread to finish and return it's result. The monadic -- context will also be merged. -- -- Example: -- --
--   setState @Int 1
--   th <- async $ do
--       setState @Int 2
--   waitAsync th
--   print =<< getState @Int -- Outputs 2
--   
waitAsync :: MonadEffect (Async thread) m => thread m a -> m a -- | Check if the asynchronous computation has finished (either normally, -- or with an exception) isAsyncDone :: MonadEffect (Async thread) m => thread n a -> m Bool -- | Abort the asynchronous exception cancelAsync :: MonadEffect (Async thread) m => thread n a -> m () -- | The type that represents the forked computation in the monad -- m that eventually computes a value of type a. -- Depending on the monad, the computation may produce zero, one or even -- multiple values of that type. newtype AsyncThread m a AsyncThread :: Async (m a) -> AsyncThread m a -- | This will discard the MonadEffect Async m -- constraint by forcing m to be IO. The functions -- doesn't actually do anything, the real implementation is given by the -- MonadEffect Async IO instance which uses the -- async package. implementAsyncViaIO :: IO a -> IO a -- | Like mapM but the supplied function is run in parallel -- asynchronously on all the elements. The results will be in the same -- order as the inputs. parallelMapM :: (MonadEffect (Async thread) m, Traversable t) => (a -> m b) -> t a -> m (t b) -- | Same as parallelMapM_ but discards the result. parallelMapM_ :: (MonadEffect (Async thread) m, Traversable t) => (a -> m b) -> t a -> m () instance GHC.Classes.Ord (Control.Effects.Async.AsyncThread m a) instance GHC.Classes.Eq (Control.Effects.Async.AsyncThread m a) instance GHC.Base.Functor m => GHC.Base.Functor (Control.Effects.Async.AsyncThread m) instance Control.Effects.Async.ThreadIdentifier Control.Effects.Async.AsyncThread instance Control.Effects.UniqueEffect Control.Effects.Async.Async GHC.Types.IO Control.Effects.Async.AsyncThread instance Control.Effects.MonadEffect (Control.Effects.Async.Async Control.Effects.Async.AsyncThread) GHC.Types.IO instance Control.Effects.Async.ThreadIdentifier thread => Control.Effects.Effect (Control.Effects.Async.Async thread) instance Control.Effects.UniqueEffect Control.Effects.Async.Async (Control.Effects.RuntimeImplemented (Control.Effects.Async.Async thread) m) thread -- | The Yield a effect lets a computation produce values -- of type a during it's execution. module Control.Effects.Yield newtype Yield a m YieldMethods :: (a -> m ()) -> Yield a m [_yield] :: Yield a m -> a -> m () -- | Output a value of type a. The semantics are determined by the -- implementation, but usually this will block until the next value is -- requested by the consumer. yield :: forall a m. MonadEffect (Yield a) m => a -> m () -- | Implement Yield by using non-determinism to output each of the -- values. This means you can use the functions from -- Control.Effects.List to choose how to consume them. For -- example, using evaluateToList will give you a list of all -- yielded values. It also means the yield calls won't block since -- all the values are requested. Other consumer functions give you more -- control. implementYieldViaNonDeterminism :: forall a m b. MonadEffect NonDeterminism m => RuntimeImplemented (Yield a) (RuntimeImplemented (Signal a ()) (ExceptT a m)) b -> m a -- | Implement Yield through an MVar. The result is a monadic -- action (the inner one) that returns one yielded value or -- Nothing if the computation is finished. All subsequent calls -- will also return Nothing. Each execution of this action -- continues execution in the provided computation, which is otherwise -- suspended. -- -- If the provided computation forks new threads and doesn't wait for -- them to finish, Nothing may be returned prematurely (in the -- sense that maybe there's still a live thread yielding values). -- -- Since the yielding is done through a shared MVar, this -- implementation is suitable to be run with multiple threads. Scheduling -- which thread gets continued is defined by the semantics of -- MVars. -- -- implementYieldViaMVar :: forall a thread m b. (MonadIO m, MonadEffect (Async thread) m) => RuntimeImplemented (Yield a) m b -> m (m (Maybe a)) -- | Implements Yield through a Chan. The resulting monadic -- action (the inner one) reads one value from the queue. Nothing -- means the provided computation is done. If the provided computation -- forks new threads and doesn't wait for them to finish, Nothing -- may be written prematurely (in the sense that maybe there's still a -- live thread yielding values). -- -- implementYieldViaChan :: forall a thread m b. (MonadIO m, MonadEffect (Async thread) m) => RuntimeImplemented (Yield a) m b -> m (m (Maybe a)) -- | A convenience function to go through all the yielded results. Use in -- combination with one of the implementations. Collects a list of -- values. traverseYielded :: Monad m => m (Maybe a) -> (a -> m b) -> m [b] -- | A convenience function to go through all the yielded results. Use in -- combination with one of the implementations. Discards the computed -- values. traverseYielded_ :: Monad m => m (Maybe a) -> (a -> m b) -> m () instance GHC.Generics.Generic (Control.Effects.Yield.Yield a m) instance Control.Effects.Effect (Control.Effects.Yield.Yield a) instance Control.Effects.UniqueEffect Control.Effects.Yield.Yield (Control.Effects.RuntimeImplemented (Control.Effects.Yield.Yield a) m) a -- | This part of the tutorial will explain the basics behind -- simple-effects and how to use the effects provided by the -- library. To learn how to implement your own effects, check out the -- other parts. -- -- You'll need to enable some extensions to follow along: -- TypeApplications, FlexibleContexts, -- OverloadedStrings, DataKinds. module Tutorial.T1_Introduction -- | In this part, we'll take a more detailed look at this library. You -- don't need to know these things to use the effects. For the most part, -- you can also implement your own without reading this part. To learn -- about that check out the next part: Tutorial.T3_CustomEffects. -- -- That being said, the details will help you understand potential -- compiler errors you might get. Also, implementing more complex effects -- does require a bit of an understanding of the internals. module Tutorial.T2_Details -- | Let's see how we can implement custom effects. We'll go through a -- couple of examples of increasing complexity. This part does not -- require going through part 2. That being said, understanding the -- details will help with understanding some of the restrictions and will -- help with compiler errors you might get. module Tutorial.T3_CustomEffects