cleff-0.2.0.0: Fast and concise extensible effects
Copyright(c) 2021 Xy Ren
LicenseBSD3
Maintainerxy.r@outlook.com
Stabilityunstable
Portabilitynon-portable (GHC only)
Safe HaskellNone
LanguageHaskell2010

Cleff.Internal.Monad

Description

This module contains the definition of the Eff monad. Most of the times, you won't need to use this module directly; user-facing functionalities are all exported via the Cleff module.

This is an internal module and its API may change even between minor versions. Therefore you should be extra careful if you're to depend on this module.

Synopsis

The Eff monad

newtype InternalHandler e Source #

The internal representation of effect handlers. This is just a natural transformation from the effect type e (Eff es) to the effect monad Eff es for any effect stack es.

In interpreting functions (see Cleff.Internal.Interpret), the user-facing Handler type is transformed into this type.

Constructors

InternalHandler 

Fields

Instances

Instances details
Typeable e => Show (InternalHandler e) Source #
show (handler :: InternalHandler E) == "Handler E"
Instance details

Defined in Cleff.Internal.Monad

newtype Eff es a Source #

The extensible effect monad. A monad Eff es is capable of performing any effect in the effect stack es, which is a type-level list that holds all effects available. However, most of the times, for flexibility, es should be a polymorphic type variable, and you should use the (:>) and (:>>) operators in constraints to indicate what effects are in the stack. For example,

Reader String :> es, State Bool :> es => Eff es Integer

allows you to perform operations of the Reader String effect and the State Bool effect in a computation returning an Integer.

Constructors

Eff

The effect monad receives an effect environment Env that contains all effect handlers and produces an IO action.

Fields

Instances

Instances details
IOE :> es => MonadBase IO (Eff es) Source #

Compatibility instance; use MonadIO if possible.

Instance details

Defined in Cleff.Internal.Base

Methods

liftBase :: IO α -> Eff es α #

IOE :> es => MonadBaseControl IO (Eff es) Source #

Compatibility instance; use MonadUnliftIO if possible.

Instance details

Defined in Cleff.Internal.Base

Associated Types

type StM (Eff es) a #

Methods

liftBaseWith :: (RunInBase (Eff es) IO -> IO a) -> Eff es a #

restoreM :: StM (Eff es) a -> Eff es a #

Monad (Eff es) Source # 
Instance details

Defined in Cleff.Internal.Monad

Methods

(>>=) :: Eff es a -> (a -> Eff es b) -> Eff es b #

(>>) :: Eff es a -> Eff es b -> Eff es b #

return :: a -> Eff es a #

Functor (Eff es) Source # 
Instance details

Defined in Cleff.Internal.Monad

Methods

fmap :: (a -> b) -> Eff es a -> Eff es b #

(<$) :: a -> Eff es b -> Eff es a #

MonadFix (Eff es) Source # 
Instance details

Defined in Cleff.Internal.Monad

Methods

mfix :: (a -> Eff es a) -> Eff es a #

Fail :> es => MonadFail (Eff es) Source # 
Instance details

Defined in Cleff.Fail

Methods

fail :: String -> Eff es a #

Applicative (Eff es) Source # 
Instance details

Defined in Cleff.Internal.Monad

Methods

pure :: a -> Eff es a #

(<*>) :: Eff es (a -> b) -> Eff es a -> Eff es b #

liftA2 :: (a -> b -> c) -> Eff es a -> Eff es b -> Eff es c #

(*>) :: Eff es a -> Eff es b -> Eff es b #

(<*) :: Eff es a -> Eff es b -> Eff es a #

IOE :> es => MonadIO (Eff es) Source # 
Instance details

Defined in Cleff.Internal.Base

Methods

liftIO :: IO a -> Eff es a #

IOE :> es => MonadThrow (Eff es) Source # 
Instance details

Defined in Cleff.Internal.Base

Methods

throwM :: Exception e => e -> Eff es a #

IOE :> es => MonadCatch (Eff es) Source # 
Instance details

Defined in Cleff.Internal.Base

Methods

catch :: Exception e => Eff es a -> (e -> Eff es a) -> Eff es a #

IOE :> es => MonadMask (Eff es) Source # 
Instance details

Defined in Cleff.Internal.Base

Methods

mask :: ((forall a. Eff es a -> Eff es a) -> Eff es b) -> Eff es b #

uninterruptibleMask :: ((forall a. Eff es a -> Eff es a) -> Eff es b) -> Eff es b #

generalBracket :: Eff es a -> (a -> ExitCase b -> Eff es c) -> (a -> Eff es b) -> Eff es (b, c) #

IOE :> es => PrimMonad (Eff es) Source # 
Instance details

Defined in Cleff.Internal.Base

Associated Types

type PrimState (Eff es) #

Methods

primitive :: (State# (PrimState (Eff es)) -> (# State# (PrimState (Eff es)), a #)) -> Eff es a #

IOE :> es => MonadUnliftIO (Eff es) Source # 
Instance details

Defined in Cleff.Internal.Base

Methods

withRunInIO :: ((forall a. Eff es a -> IO a) -> IO b) -> Eff es b #

Semigroup a => Semigroup (Eff es a) Source # 
Instance details

Defined in Cleff.Internal.Monad

Methods

(<>) :: Eff es a -> Eff es a -> Eff es a #

sconcat :: NonEmpty (Eff es a) -> Eff es a #

stimes :: Integral b => b -> Eff es a -> Eff es a #

Monoid a => Monoid (Eff es a) Source # 
Instance details

Defined in Cleff.Internal.Monad

Methods

mempty :: Eff es a #

mappend :: Eff es a -> Eff es a -> Eff es a #

mconcat :: [Eff es a] -> Eff es a #

type PrimState (Eff es) Source # 
Instance details

Defined in Cleff.Internal.Base

type PrimState (Eff es) = RealWorld
type StM (Eff es) a Source # 
Instance details

Defined in Cleff.Internal.Base

type StM (Eff es) a = a

Effect environment

data Env (es :: [Effect]) Source #

The effect environment that corresponds effects in the stack to their respective InternalHandlers. This structure simulates memory: handlers are retrieved via pointers (HandlerPtrs), and for each effect in the stack we can either change what pointer it uses or change the handler the pointer points to. The former is used for global effect interpretation (reinterpretN) and the latter for local interpretation (toEffWith) in order to retain correct HO semantics. For more details on this see https://github.com/re-xyr/cleff/issues/5.

data HandlerPtr (e :: Effect) Source #

A pointer to InternalHandler in an Env.

Instances

Instances details
Eq (HandlerPtr e) Source #

Pointer equality.

Instance details

Defined in Cleff.Internal.Monad

Methods

(==) :: HandlerPtr e -> HandlerPtr e -> Bool #

(/=) :: HandlerPtr e -> HandlerPtr e -> Bool #

Ord (HandlerPtr e) Source #

An arbitrary total order on the pointers.

Instance details

Defined in Cleff.Internal.Monad

emptyEnv :: Env '[] Source #

Create an empty Env with no address allocated.

adjustEnv :: forall es' es. (Rec HandlerPtr es -> Rec HandlerPtr es') -> Env es -> Env es' Source #

Adjust the effect stack via an function over Rec.

allocaEnv :: forall e es. Env es -> (# HandlerPtr e, Env es #) Source #

Allocate a new, empty address for a handler. \( O(1) \).

readEnv :: forall e es. Elem e es => Env es -> InternalHandler e Source #

Read the handler a pointer points to. \( O(1) \).

writeEnv :: forall e es. HandlerPtr e -> InternalHandler e -> Env es -> Env es Source #

Overwrite the handler a pointer points to. \( O(1) \).

replaceEnv :: forall e es. Elem e es => HandlerPtr e -> InternalHandler e -> Env es -> Env es Source #

Replace the handler pointer of an effect in the stack. \( O(n) \).

appendEnv :: forall e es. HandlerPtr e -> InternalHandler e -> Env es -> Env (e ': es) Source #

Add a new effect to the stack with its corresponding handler pointer. \( O(n) \).

updateEnv :: forall es es'. Env es' -> Env es -> Env es Source #

Use the state of LHS as a newer version for RHS. \( O(1) \).

Performing effect operations

class KnownList (es :: [k]) #

The list es list is concrete, i.e. is of the form '[a1, a2, ..., an], i.e. is not a type variable.

Instances

Instances details
KnownList ('[] :: [k]) 
Instance details

Defined in Data.Rec.SmallArray

Methods

reifyLen :: Int

KnownList es => KnownList (e ': es :: [k]) 
Instance details

Defined in Data.Rec.SmallArray

Methods

reifyLen :: Int

class KnownList es => Subset (es :: [k]) (es' :: [k]) #

es is a subset of es'.

Instances

Instances details
Subset ('[] :: [k]) (es :: [k]) 
Instance details

Defined in Data.Rec.SmallArray

Methods

reifyIndices :: [Int]

(Subset es es', Elem e es') => Subset (e ': es :: [k]) (es' :: [k]) 
Instance details

Defined in Data.Rec.SmallArray

Methods

reifyIndices :: [Int]

send :: e :> es => e (Eff es) ~> Eff es Source #

Perform an effect operation, i.e. a value of an effect type e :: Effect. This requires e to be in the effect stack.

sendVia :: e :> es' => (Eff es ~> Eff es') -> e (Eff es) ~> Eff es' Source #

Perform an action in another effect stack via a transformation to that stack; in other words, this function "maps" the effect operation from effect stack es to es'. This is a generalization of send; end users most likely won't need to use this.

send = sendVia id