-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Fast and concise extensible effects -- -- Please see the README on GitHub at -- https://github.com/re-xyr/cleff#readme @package cleff @version 0.1.0.0 -- | This module contains utility functions for Any. -- -- 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. module Data.Any -- | The type constructor Any is type to which you can unsafely -- coerce any lifted type, and back. More concretely, for a lifted type -- t and value x :: t, -- unsafeCoerce -- (unsafeCoerce x :: Any) :: t is equivalent to x. type family Any :: k -- | Coerce Any to a boxed value. This is generally unsafe -- and it is your responsibility to ensure that the type you're coercing -- into is the original type that the Any is coerced from. fromAny :: Any -> a -- | Coerce any boxed value into Any. toAny :: a -> Any -- | This module defines an immutable extensible record type, similar to -- vinyl and data-diverse. However this implementation -- focuses on fast reads, hence has very different performance -- characteristics from other libraries: -- --
-- 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. newtype Eff es a Eff :: (Env es -> IO a) -> Eff es a [unEff] :: Eff es a -> Env es -> IO a -- | The list es list is concrete, i.e. is of the form '[a1, -- a2, ..., an], i.e. is not a type variable. class KnownList (es :: [k]) -- | es is a subset of es'. class KnownList es => Subset (es :: [k]) (es' :: [k]) -- | Perform an effect operation, i.e. a value of an effect type -- e :: Effect. This requires e to be in the -- effect stack. send :: e :> es => e (Eff es) ~> Eff es instance Control.Monad.Fix.MonadFix (Cleff.Internal.Monad.Eff es) instance GHC.Base.Monad (Cleff.Internal.Monad.Eff es) instance GHC.Base.Applicative (Cleff.Internal.Monad.Eff es) instance GHC.Base.Functor (Cleff.Internal.Monad.Eff es) instance GHC.Base.Monoid a => GHC.Base.Monoid (Cleff.Internal.Monad.Eff es a) instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Cleff.Internal.Monad.Eff es a) instance Data.Typeable.Internal.Typeable e => GHC.Show.Show (Cleff.Internal.Monad.InternalHandler e) -- | This module contains Template Haskell functions for generating -- definitions of functions that send effect operations. You mostly won't -- want to import this module directly; The Cleff module reexports -- the main functionalities of this 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. module Cleff.Internal.TH -- | For a datatype T representing an effect, -- makeEffect T generates functions defintions for -- performing the operations of T via send. The naming -- rule is changing the first uppercase letter in the constructor name to -- lowercase or removing the : symbol in the case of operator -- constructors. Also, this function will preserve any fixity -- declarations defined on the constructors. -- -- Because of the limitations of Template Haskell, all constructors of -- T should be polymorphic in the monad type, if they are -- to be used by makeEffect. For example, this is not OK: -- --
-- data Limited :: Effect where -- Noop :: Limited (Eff es) () ---- -- because the monad type Eff es is not a fully -- polymorphic type variable. -- -- This function is also "weaker" than polysemy's -- makeSem, because this function cannot properly handle some -- cases involving complex higher order effects. Those cases are rare, -- though. See the tests for more details. makeEffect :: Name -> Q [Dec] -- | Like makeEffect, but doesn't generate type signatures. This is -- useful when you want to attach Haddock documentation to the function -- signature, e.g.: -- --
-- data Identity :: Effect where -- Noop :: Identity m () -- makeEffect_ ''Identity -- -- -- | Perform nothing at all. -- noop :: Identity :> es => Eff es () ---- -- Be careful that the function signatures must be added after the -- makeEffect_ call. makeEffect_ :: Name -> Q [Dec] -- | This module contains functions for interpreting effects. Most of the -- times you won't need to import this directly; the module Cleff -- reexports most of the functionalities. -- -- 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. module Cleff.Internal.Interpret -- | Lift a computation into a bigger effect stack with one more effect. -- For a more general version see raiseN. raise :: forall e es. Eff es ~> Eff (e : es) -- | Lift a computation into a bigger effect stack with arbitrarily more -- effects. This function requires TypeApplications. raiseN :: forall es' es. KnownList es' => Eff es ~> Eff (es' ++ es) -- | Lift a computation with a fixed, known effect stack into some superset -- of the stack. inject :: forall es' es. Subset es' es => Eff es' ~> Eff es -- | Eliminate a duplicate effect from the top of the effect stack. For a -- more general version see subsumeN. subsume :: forall e es. e :> es => Eff (e : es) ~> Eff es -- | Eliminate several duplicate effects from the top of the effect stack. -- This function requires TypeApplications. subsumeN :: forall es' es. Subset es' es => Eff (es' ++ es) ~> Eff es -- | The typeclass that indicates a handler scope, handling effect -- e sent from the effect stack esSend in the effect -- stack es. -- -- You should not define instances for this typeclass whatsoever. class Handling e es esSend | e -> es esSend, es -> e esSend, esSend -> e es -- | Get the send-site Env. sendEnv :: Handling e es esSend => Env esSend -- | The type of an effect handler, which is a function that -- transforms an effect e from an arbitrary effect stack into -- computations in the effect stack es. type Handler e es = forall esSend. Handling e es esSend => e (Eff esSend) ~> Eff es -- | The type of a simple transformation function from effect e to -- e'. type Translator e e' = forall esSend. e (Eff esSend) ~> e' (Eff esSend) -- | Interpret an effect e in terms of effects in the effect stack -- es with an effect handler. interpret :: forall e es. Handler e es -> Eff (e : es) ~> Eff es -- | Like interpret, but adds a new effect e' that can be -- used in the handler. reinterpret :: forall e' e es. Handler e (e' : es) -> Eff (e : es) ~> Eff (e' : es) -- | Like reinterpret, but adds two new effects. reinterpret2 :: forall e' e'' e es. Handler e (e' : (e'' : es)) -> Eff (e : es) ~> Eff (e' : (e'' : es)) -- | Like reinterpret, but adds three new effects. reinterpret3 :: forall e' e'' e''' e es. Handler e (e' : (e'' : (e''' : es))) -> Eff (e : es) ~> Eff (e' : (e'' : (e''' : es))) -- | Like reinterpret, but adds arbitrarily many new effects. This -- function requires TypeApplications. reinterpretN :: forall es' e es. KnownList es' => Handler e (es' ++ es) -> Eff (e : es) ~> Eff (es' ++ es) -- | Respond to an effect while being able to leave it unhandled (i.e. you -- can resend the effects in the handler). interpose :: forall e es. e :> es => Handler e es -> Eff es ~> Eff es -- | Like interpose, but allows to introduce one new effect to use -- in the handler. impose :: forall e' e es. e :> es => Handler e (e' : es) -> Eff es ~> Eff (e' : es) -- | Like impose, but allows introducing arbitrarily many effects. -- This requires TypeApplications. imposeN :: forall es' e es. (KnownList es', e :> es) => Handler e (es' ++ es) -> Eff es ~> Eff (es' ++ es) -- | Interpret an effect in terms of another effect in the stack via a -- simple Translator. transform :: forall e' e es. e' :> es => Translator e e' -> Eff (e : es) ~> Eff es -- | Like transform, but instead of using an effect in stack, add a -- new one to the top of it. translate :: forall e' e es. Translator e e' -> Eff (e : es) ~> Eff (e' : es) -- | Run a computation in the current effect stack. This is useful for -- interpreting higher-order effects, like a bracketing effect: -- --
-- data Resource m a where -- Bracket :: m a -> (a -> m ()) -> (a -> m b) -> Resource m b ---- --
-- Bracket alloc dealloc use -> -- bracket -- (toEff alloc) -- (toEff . dealloc) -- (toEff . use) --toEff :: Handling e es esSend => Eff esSend ~> Eff es -- | Run a computation in the current effect stack, but handles the current -- effect inside the computation differently by providing a new -- Handler. This is useful for interpreting effects with local -- contexts, like Local: -- --
-- runReader :: r -> Eff (Reader r ': es) ~> Eff es -- runReader x = interpret (handle x) -- where -- handle :: r -> Handler (Reader r) es -- handle r = \case -- Ask -> pure r -- Local f m -> toEffWith (handle $ f r) m --toEffWith :: Handling e es esSend => Handler e es -> Eff esSend ~> Eff es -- | Temporarily gain the ability to lift some Eff es -- actions into Eff esSend. This is useful for dealing -- with effect operations with the monad type in the negative position, -- which means it's unlikely that you need to use this function in -- implementing your effects. withFromEff :: Handling e es esSend => ((Eff es ~> Eff esSend) -> Eff esSend a) -> Eff es a -- | This module contains the IOE effect together with a few -- primitives for using it, as well as interpretation combinators for -- IO-related effects. It is not usually needed because safe -- functionalities are re-exported in 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. module Cleff.Internal.Base -- | The effect for lifting and unlifting the IO monad, allowing you -- to use MonadIO, MonadUnliftIO, PrimMonad, -- MonadCatch, MonadThrow and MonadMask -- functionalities. This is the "final" effect that most effects -- eventually are interpreted into. For example, you can do: -- --
-- log :: IOE :> es => Eff es () -- log = liftIO (putStrLn "Test logging") ---- -- It is not recommended to use this effect in application code, as it is -- too liberal and allows arbitrary IO. Ideally, this is only used in -- interpreting more fine-grained effects. -- -- Note that this is not a real effect and cannot be interpreted -- in any way besides thisIsPureTrustMe and runIOE. It is -- similar to Polysemy's Final effect which also cannot be -- interpreted. This is mainly for performance concern, but also that -- there doesn't really exist reasonable interpretations other than the -- current one, given the underlying implementation of the Eff -- monad. -- -- IOE can be a real effect though, and you can enable the -- dynamic-ioe build flag to have that. However it is only for -- reference purposes and should not be used in production code. data IOE :: Effect -- | Lift an IO computation into Eff. This function is -- highly unsafe and should not be used directly; use -- liftIO instead, or if you're interpreting higher-order effects, -- use fromIO. primLiftIO :: IO a -> Eff es a -- | Give a runner function a way to run Eff actions as an IO -- computation. This function is highly unsafe and should not be -- used directly; use withRunInIO instead, or if you're -- interpreting higher-order effects, use withToIO. primUnliftIO :: ((Eff es ~> IO) -> IO a) -> Eff es a -- | Unsafely eliminate an IOE effect from the top of the effect -- stack. This is mainly for implementing effects that uses IO but -- does not do anything really impure (i.e. can be safely used -- unsafeDupablePerformIO on), such as a State effect. thisIsPureTrustMe :: Eff (IOE : es) ~> Eff es -- | Unwrap an Eff computation with side effects into an IO -- computation, given that all effects other than IOE are -- interpreted. runIOE :: Eff '[IOE] ~> IO -- | Unwrap a pure Eff computation into a pure value, given that all -- effects are interpreted. runPure :: Eff '[] a -> a -- | The type of an IO effect handler, which is a function -- that transforms an effect e into IO computations. This -- is used for interpretIO. type HandlerIO e es = forall esSend. (Handling e es esSend) => e (Eff esSend) ~> IO -- | Interpret an effect in terms of IO, by transforming an effect -- into IO computations. -- --
-- interpretIO f = interpret (liftIO . f) --interpretIO :: IOE :> es => HandlerIO e es -> Eff (e : es) ~> Eff es -- | Temporarily gain the ability to unlift an Eff esSend -- computation into IO. This is useful for dealing with -- higher-order effects that involves IO. withToIO :: (Handling e es esSend, IOE :> es) => ((Eff esSend ~> IO) -> IO a) -> Eff es a -- | Lift an IO computation into Eff esSend. This is -- useful for dealing with effect operations with the monad type in the -- negative position within IOE, like masking. fromIO :: (Handling e es esSend, IOE :> es) => IO ~> Eff esSend instance (Cleff.Internal.Base.IOE Cleff.Internal.Effect.:> es) => Control.Monad.IO.Class.MonadIO (Cleff.Internal.Monad.Eff es) instance (Cleff.Internal.Base.IOE Cleff.Internal.Effect.:> es) => Control.Monad.IO.Unlift.MonadUnliftIO (Cleff.Internal.Monad.Eff es) instance (Cleff.Internal.Base.IOE Cleff.Internal.Effect.:> es) => Control.Monad.Catch.MonadThrow (Cleff.Internal.Monad.Eff es) instance (Cleff.Internal.Base.IOE Cleff.Internal.Effect.:> es) => Control.Monad.Catch.MonadCatch (Cleff.Internal.Monad.Eff es) instance (Cleff.Internal.Base.IOE Cleff.Internal.Effect.:> es) => Control.Monad.Catch.MonadMask (Cleff.Internal.Monad.Eff es) instance (Cleff.Internal.Base.IOE Cleff.Internal.Effect.:> es) => Control.Monad.Base.MonadBase GHC.Types.IO (Cleff.Internal.Monad.Eff es) instance (Cleff.Internal.Base.IOE Cleff.Internal.Effect.:> es) => Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO (Cleff.Internal.Monad.Eff es) instance (Cleff.Internal.Base.IOE Cleff.Internal.Effect.:> es) => Control.Monad.Primitive.PrimMonad (Cleff.Internal.Monad.Eff es) -- | This library implements an extensible effects system, where -- sets of monadic actions ("effects") are encoded as datatypes, tracked -- at the type level and can have multiple different implementations. -- This means you can swap out implementations of certain monadic actions -- in mock tests or in different environments. The notion of "effect" is -- general here: it can be an IO-performing side effect, or just -- obtaining the value of a static global environment. -- -- In particular, this library consists of -- --
-- 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. data Eff es a -- | e :> es means the effect e is present in -- the effect stack es, and therefore can be used in an -- Eff es computation. type (:>) = Elem infix 0 :> -- | xs :>> es means the list of effects xs -- are all present in the effect stack es. This is a convenient -- type alias for (e1 :> es, ..., en :> es). type family xs :>> es :: Constraint infix 0 :>> -- | The type of effects. An effect e m a takes an effect monad -- type m :: Type -> Type and a result type -- a :: Type. type Effect = (Type -> Type) -> Type -> Type -- | The effect for lifting and unlifting the IO monad, allowing you -- to use MonadIO, MonadUnliftIO, PrimMonad, -- MonadCatch, MonadThrow and MonadMask -- functionalities. This is the "final" effect that most effects -- eventually are interpreted into. For example, you can do: -- --
-- log :: IOE :> es => Eff es () -- log = liftIO (putStrLn "Test logging") ---- -- It is not recommended to use this effect in application code, as it is -- too liberal and allows arbitrary IO. Ideally, this is only used in -- interpreting more fine-grained effects. -- -- Note that this is not a real effect and cannot be interpreted -- in any way besides thisIsPureTrustMe and runIOE. It is -- similar to Polysemy's Final effect which also cannot be -- interpreted. This is mainly for performance concern, but also that -- there doesn't really exist reasonable interpretations other than the -- current one, given the underlying implementation of the Eff -- monad. -- -- IOE can be a real effect though, and you can enable the -- dynamic-ioe build flag to have that. However it is only for -- reference purposes and should not be used in production code. data IOE :: Effect -- | Unwrap a pure Eff computation into a pure value, given that all -- effects are interpreted. runPure :: Eff '[] a -> a -- | Unwrap an Eff computation with side effects into an IO -- computation, given that all effects other than IOE are -- interpreted. runIOE :: Eff '[IOE] ~> IO -- | Perform an effect operation, i.e. a value of an effect type -- e :: Effect. This requires e to be in the -- effect stack. send :: e :> es => e (Eff es) ~> Eff es -- | For a datatype T representing an effect, -- makeEffect T generates functions defintions for -- performing the operations of T via send. The naming -- rule is changing the first uppercase letter in the constructor name to -- lowercase or removing the : symbol in the case of operator -- constructors. Also, this function will preserve any fixity -- declarations defined on the constructors. -- -- Because of the limitations of Template Haskell, all constructors of -- T should be polymorphic in the monad type, if they are -- to be used by makeEffect. For example, this is not OK: -- --
-- data Limited :: Effect where -- Noop :: Limited (Eff es) () ---- -- because the monad type Eff es is not a fully -- polymorphic type variable. -- -- This function is also "weaker" than polysemy's -- makeSem, because this function cannot properly handle some -- cases involving complex higher order effects. Those cases are rare, -- though. See the tests for more details. makeEffect :: Name -> Q [Dec] -- | Like makeEffect, but doesn't generate type signatures. This is -- useful when you want to attach Haddock documentation to the function -- signature, e.g.: -- --
-- data Identity :: Effect where -- Noop :: Identity m () -- makeEffect_ ''Identity -- -- -- | Perform nothing at all. -- noop :: Identity :> es => Eff es () ---- -- Be careful that the function signatures must be added after the -- makeEffect_ call. makeEffect_ :: Name -> Q [Dec] -- | Lift a computation into a bigger effect stack with one more effect. -- For a more general version see raiseN. raise :: forall e es. Eff es ~> Eff (e : es) -- | Lift a computation into a bigger effect stack with arbitrarily more -- effects. This function requires TypeApplications. raiseN :: forall es' es. KnownList es' => Eff es ~> Eff (es' ++ es) -- | Lift a computation with a fixed, known effect stack into some superset -- of the stack. inject :: forall es' es. Subset es' es => Eff es' ~> Eff es -- | Eliminate a duplicate effect from the top of the effect stack. For a -- more general version see subsumeN. subsume :: forall e es. e :> es => Eff (e : es) ~> Eff es -- | Eliminate several duplicate effects from the top of the effect stack. -- This function requires TypeApplications. subsumeN :: forall es' es. Subset es' es => Eff (es' ++ es) ~> Eff es -- | The list es list is concrete, i.e. is of the form '[a1, -- a2, ..., an], i.e. is not a type variable. class KnownList (es :: [k]) -- | es is a subset of es'. class KnownList es => Subset (es :: [k]) (es' :: [k]) -- | The type of an effect handler, which is a function that -- transforms an effect e from an arbitrary effect stack into -- computations in the effect stack es. type Handler e es = forall esSend. Handling e es esSend => e (Eff esSend) ~> Eff es -- | Interpret an effect e in terms of effects in the effect stack -- es with an effect handler. interpret :: forall e es. Handler e es -> Eff (e : es) ~> Eff es -- | Like interpret, but adds a new effect e' that can be -- used in the handler. reinterpret :: forall e' e es. Handler e (e' : es) -> Eff (e : es) ~> Eff (e' : es) -- | Like reinterpret, but adds two new effects. reinterpret2 :: forall e' e'' e es. Handler e (e' : (e'' : es)) -> Eff (e : es) ~> Eff (e' : (e'' : es)) -- | Like reinterpret, but adds three new effects. reinterpret3 :: forall e' e'' e''' e es. Handler e (e' : (e'' : (e''' : es))) -> Eff (e : es) ~> Eff (e' : (e'' : (e''' : es))) -- | Like reinterpret, but adds arbitrarily many new effects. This -- function requires TypeApplications. reinterpretN :: forall es' e es. KnownList es' => Handler e (es' ++ es) -> Eff (e : es) ~> Eff (es' ++ es) -- | Respond to an effect while being able to leave it unhandled (i.e. you -- can resend the effects in the handler). interpose :: forall e es. e :> es => Handler e es -> Eff es ~> Eff es -- | Like interpose, but allows to introduce one new effect to use -- in the handler. impose :: forall e' e es. e :> es => Handler e (e' : es) -> Eff es ~> Eff (e' : es) -- | Like impose, but allows introducing arbitrarily many effects. -- This requires TypeApplications. imposeN :: forall es' e es. (KnownList es', e :> es) => Handler e (es' ++ es) -> Eff es ~> Eff (es' ++ es) -- | The type of an IO effect handler, which is a function -- that transforms an effect e into IO computations. This -- is used for interpretIO. type HandlerIO e es = forall esSend. (Handling e es esSend) => e (Eff esSend) ~> IO -- | Interpret an effect in terms of IO, by transforming an effect -- into IO computations. -- --
-- interpretIO f = interpret (liftIO . f) --interpretIO :: IOE :> es => HandlerIO e es -> Eff (e : es) ~> Eff es -- | The type of a simple transformation function from effect e to -- e'. type Translator e e' = forall esSend. e (Eff esSend) ~> e' (Eff esSend) -- | Interpret an effect in terms of another effect in the stack via a -- simple Translator. transform :: forall e' e es. e' :> es => Translator e e' -> Eff (e : es) ~> Eff es -- | Like transform, but instead of using an effect in stack, add a -- new one to the top of it. translate :: forall e' e es. Translator e e' -> Eff (e : es) ~> Eff (e' : es) -- | The typeclass that indicates a handler scope, handling effect -- e sent from the effect stack esSend in the effect -- stack es. -- -- You should not define instances for this typeclass whatsoever. class Handling e es esSend | e -> es esSend, es -> e esSend, esSend -> e es -- | Run a computation in the current effect stack. This is useful for -- interpreting higher-order effects, like a bracketing effect: -- --
-- data Resource m a where -- Bracket :: m a -> (a -> m ()) -> (a -> m b) -> Resource m b ---- --
-- Bracket alloc dealloc use -> -- bracket -- (toEff alloc) -- (toEff . dealloc) -- (toEff . use) --toEff :: Handling e es esSend => Eff esSend ~> Eff es -- | Run a computation in the current effect stack, but handles the current -- effect inside the computation differently by providing a new -- Handler. This is useful for interpreting effects with local -- contexts, like Local: -- --
-- runReader :: r -> Eff (Reader r ': es) ~> Eff es -- runReader x = interpret (handle x) -- where -- handle :: r -> Handler (Reader r) es -- handle r = \case -- Ask -> pure r -- Local f m -> toEffWith (handle $ f r) m --toEffWith :: Handling e es esSend => Handler e es -> Eff esSend ~> Eff es -- | Temporarily gain the ability to lift some Eff es -- actions into Eff esSend. This is useful for dealing -- with effect operations with the monad type in the negative position, -- which means it's unlikely that you need to use this function in -- implementing your effects. withFromEff :: Handling e es esSend => ((Eff es ~> Eff esSend) -> Eff esSend a) -> Eff es a -- | Temporarily gain the ability to unlift an Eff esSend -- computation into IO. This is useful for dealing with -- higher-order effects that involves IO. withToIO :: (Handling e es esSend, IOE :> es) => ((Eff esSend ~> IO) -> IO a) -> Eff es a -- | Lift an IO computation into Eff esSend. This is -- useful for dealing with effect operations with the monad type in the -- negative position within IOE, like masking. fromIO :: (Handling e es esSend, IOE :> es) => IO ~> Eff esSend -- | The type of natural transformations from functor f to -- g. type f ~> g = forall a. f a -> g a infixr 0 ~> -- | Type level list concatenation. type family xs ++ ys infixr 5 ++ -- | Monads in which IO computations may be embedded. Any monad -- built by applying a sequence of monad transformers to the IO -- monad will be an instance of this class. -- -- Instances should satisfy the following laws, which state that -- liftIO is a transformer of monads: -- -- class Monad m => MonadIO (m :: Type -> Type) -- | Lift a computation from the IO monad. liftIO :: MonadIO m => IO a -> m a -- | Monads which allow their actions to be run in IO. -- -- While MonadIO allows an IO action to be lifted into -- another monad, this class captures the opposite concept: allowing you -- to capture the monadic context. Note that, in order to meet the laws -- given below, the intuition is that a monad must have no monadic state, -- but may have monadic context. This essentially limits -- MonadUnliftIO to ReaderT and IdentityT -- transformers on top of IO. -- -- Laws. For any value u returned by askUnliftIO, it must -- meet the monad transformer laws as reformulated for -- MonadUnliftIO: -- --
unliftIO u . return = return
unliftIO u (m >>= f) = unliftIO u m >>= unliftIO -- u . f
askUnliftIO >>= \u -> (liftIO . unliftIO u) m = -- m