| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Control.Effect.Primitive
Contents
Synopsis
- class Monad m => Carrier m where
- type EffPrimHandler e m = forall x. e m x -> m x
- interpretPrimSimple :: forall e m a p. (RepresentationalEff e, Threaders '[ReaderThreads] m p, ReaderThreads '[e], Carrier m) => EffPrimHandler e m -> InterpretPrimSimpleC e m a -> m a
- interpretPrimViaHandler :: forall h e m a. PrimHandler h e m => InterpretPrimC h e m a -> m a
- class (RepresentationalEff e, Carrier m) => PrimHandler (h :: *) e m where
- effPrimHandler :: EffPrimHandler e m
- interpretPrim :: forall e m a. (RepresentationalEff e, Carrier m) => EffPrimHandler e m -> InterpretPrimReifiedC e m a -> m a
- class Threads t p where
- class RepresentationalEff e => ThreadsEff t e where
- data InterpretPrimSimpleC (e :: Effect) (m :: * -> *) a
- data InterpretPrimC (s :: *) (e :: Effect) (m :: * -> *) a
- type InterpretPrimReifiedC e m a = forall s. ReifiesPrimHandler s e m => InterpretPrimC (ViaReifiedH s) e m a
Primitive effects
class Monad m => Carrier m Source #
The class of effect carriers, and the underlying mechanism with which effects are implemented.
Each carrier is able to implement a number of derived effects, and primitive effects. Users usually only interact with derived effects, as these determine the effects that users have access to.
The standard interpretation tools are typically powerful enough to
let you avoid making instances of this class directly. If you need to make
your own instance of Carrier, import Control.Effect.Carrier and consult the
wiki.
Minimal complete definition
Associated Types
type Derivs m :: [Effect] Source #
The derived effects that m carries. Each derived effect is eventually
reformulated into terms of the primitive effects or other
effects in Prims m.Derivs m
In application code, you gain access to effects by placing membership
constraints upon . You can use Derivs mEff or Effs for this
purpose.
Although rarely relevant for users, can also contain effects
that aren't expressed in terms of other effects, as longs as the handlers
for those effects can be lifted generically using Derivs mlift. Such effects don't
need to be part of , which is exclusively for primitive effects
whose handlers need special treatment to be lifted.Prims m
For example, first order effects such as State
never need to be part of . Certain higher-order effects -
such as Prims mCont - can also be handled such that they
never need to be primitive.
type Prims m :: [Effect] Source #
The primitive effects that m carries. These are higher-order effects
whose handlers aren't expressed in terms of other effects, and thus need to
be lifted on a carrier-by-carrier basis.
Never place membership constraints on .
You should only gain access to effects by placing membership constraints
on Prims m.Derivs m
However, running interpreters may place other kinds of constraints upon
, namely threading constraints, marked by the use of
Prims mThreaders.
If you want to run such an effect interpreter inside application code, you
have to propagate such threading constraints through your application.
should only contain higher-order effects that can't be lifted
generically using Prims mlift. Any other effects can be placed in .Derivs m
Instances
Interpretation of primitive effects
type EffPrimHandler e m = forall x. e m x -> m x Source #
The type of effect handlers for a primitive effect e with current
carrier m.
Unlike EffHandlers, EffPrimHandlers have direct access to m,
giving them significantly more powerful.
That said, you should interpret your own effects as primitives only as a
last resort. Every primitive effect comes at the cost of enormous amounts
of boilerplate: namely, the need for a ThreadsEff instance for every
monad transformer that can thread that effect.
Some effects in this library are intended to be used as primitive effects,
such as Regional. Try to use such effects
to gain the power you need to interpret your effects instead of
defining your own primitive effects, since the primitive effects offered
in this library already have ThreadsEff instances defined for them.
interpretPrimSimple
interpretPrimSimple :: forall e m a p. (RepresentationalEff e, Threaders '[ReaderThreads] m p, ReaderThreads '[e], Carrier m) => EffPrimHandler e m -> InterpretPrimSimpleC e m a -> m a Source #
A significantly slower variant of interpretPrim that doesn't have
a higher-ranked type, making it much easier to use partially applied.
*Only interpret your own effects as primitives as a last resort.
See EffPrimHandler.
Note the ReaderThreads '[e] constraint, meaning
you need to define a ThreadsEff e (ReaderT i) instance in order
to use interpretPrimSimple.
interpretPrimViaHandler
interpretPrimViaHandler :: forall h e m a. PrimHandler h e m => InterpretPrimC h e m a -> m a Source #
Interpret an effect as a new primitive effect by using
an explicit PrimHandler instance.
See PrimHandler for more information.
Only interpret your own effects as primitives as a last resort.
See EffPrimHandler.
Unlike interpretPrim, this does not have a higher-rank type,
making it easier to use partially applied, and unlike
interpretPrimSimple doesn't sacrifice performance.
class (RepresentationalEff e, Carrier m) => PrimHandler (h :: *) e m where Source #
The class of effect handlers for primitive effects.
Instances of this class can be used together interpretPrimViaHandler
in order to interpret primitive effects.
h is the tag for the handler, e is the effect to interpret,
and m is the Carrier on which the handler operates.
To define your own interpreter using this method, create a new
datatype without any constructors to serve as the tag
for the handler, and then define a PrimHandler instance for it.
Then, you can use your handler to interpret effects with
interpretPrimViaHandler.
Alternatively, you can use interpretPrim or interpretPrimSimple,
which lets you avoid the need to define instances of PrimHandler,
but come at other costs.
Only interpret your own effects as primitives as a last resort.
See EffPrimHandler.
Methods
effPrimHandler :: EffPrimHandler e m Source #
Instances
interpretPrim
interpretPrim :: forall e m a. (RepresentationalEff e, Carrier m) => EffPrimHandler e m -> InterpretPrimReifiedC e m a -> m a Source #
Interpret an effect as a new primitive effect.
*Only interpret your own effects as primitives as a last resort.
See EffPrimHandler.
This has a higher-rank type, as it makes use of InterpretPrimReifiedC.
This makes interpretPrim very difficult to use partially applied.
In particular, it can't be composed using . You must use
paranthesis or .$.
Consider using interpretPrimSimple instead if performance is secondary.
Threading primitive effects
class Threads t p where Source #
is satisfied if Threads t pThreadsEff t e instances are defined for
each effect e in p. By using the constraint, you're
able to lift Threads t pAlgebras over p from any monad m to t m. This is useful
when defining custom Carrier instances.
Note that you should not place a constraint if Threads t pt is
simply a newtype over an existsing monad transformer u that already has
ThreadsEff instances defined for it. Instead, you should place a
constraint, and use its Threads u pthread by coercing the resulting
algebra from to Algebra p (u m)'.
That way, you avoid having to define redundant Algebra p (t m)ThreadsEff instances for
every newtype of a monad transformer.
Threads forms the basis of threading constraints
(see Threaders), and every threading constraint offered
in the library makes use of Threads in one way or another.
class RepresentationalEff e => ThreadsEff t e where Source #
An instance of ThreadsEff represents the ability for a monad transformer
t to thread a primitive effect e -- i.e. lift handlers of that effect.
Instances of ThreadsEff are accumulated into entire stacks of primitive
effects by Threads.
You only need to make ThreadsEff instances for monad transformers that
aren't simply newtypes over existing monad transformers. You also don't need
to make them for IdentityT.
Instances
Carriers
data InterpretPrimSimpleC (e :: Effect) (m :: * -> *) a Source #
Instances
data InterpretPrimC (s :: *) (e :: Effect) (m :: * -> *) a Source #
Instances
type InterpretPrimReifiedC e m a = forall s. ReifiesPrimHandler s e m => InterpretPrimC (ViaReifiedH s) e m a Source #