-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | An easy to use, performant extensible effects library. -- -- An easy to use, performant extensible effects library with seamless -- integration with the existing Haskell ecosystem. -- -- This library provides core definitions with a minimal dependency -- footprint. See the effectful package for the -- "batteries-included" variant. @package effectful-core @version 2.2.0.0 -- | Type-safe indexing for Env. -- -- This module is intended for internal use only, and may change without -- warning in subsequent releases. module Effectful.Internal.Effect -- | The kind of effects. type Effect = (Type -> Type) -> Type -> Type -- | A constraint that requires that a particular effect e is a -- member of the type-level list es. This is used to -- parameterize an Eff computation over an arbitrary list of -- effects, so long as e is somewhere in the list. -- -- For example, a computation that only needs access to a mutable value -- of type Integer would have the following type: -- --
--   State Integer :> es => Eff es ()
--   
class (e :: Effect) :> (es :: [Effect]) -- | Get the position of e in es. -- -- Note: GHC is kind enough to cache these values as they're top -- level CAFs, so the lookup is amortized O(1) without any -- language level tricks. reifyIndex :: (:>) e es => Int -- | Convenience operator for expressing that a function uses multiple -- effects in a more concise way than enumerating them all with -- (:>). -- --
--   [E1, E2, ..., En] :>> es ≡ (E1 :> es, E2 :> es, ..., En :> es)
--   
-- | Deprecated: Usage of (:>>) slows down GHC too much, so it -- will be removed in 3.0.0.0. See -- https://github.com/haskell-effectful/effectful/issues/52#issuecomment-1269155485 -- for more information. type family xs :>> es :: Constraint -- | Provide evidence that xs is a subset of es. class Subset (xs :: [Effect]) (es :: [Effect]) reifyIndices :: Subset xs es => [Int] -- | The kind of types with lifted values. For example Int :: -- Type. type Type = TYPE LiftedRep instance Effectful.Internal.Effect.Subset '[] es instance (e Effectful.Internal.Effect.:> es, Effectful.Internal.Effect.Subset xs es) => Effectful.Internal.Effect.Subset (e : xs) es instance (TypeError ...) => e Effectful.Internal.Effect.:> '[] instance e Effectful.Internal.Effect.:> (e : es) instance (e Effectful.Internal.Effect.:> es) => e Effectful.Internal.Effect.:> (x : es) module Effectful.Internal.Env -- | A strict (WHNF), thread local, mutable, extensible record -- indexed by types of kind Effect. -- -- Warning: the environment is a mutable data structure and cannot be -- simultaneously used from multiple threads under any circumstances. -- -- In order to pass it to a different thread, you need to perform a deep -- copy with the cloneEnv funtion. -- -- Offers very good performance characteristics for most often performed -- operations: -- -- data Env (es :: [Effect]) Env :: !Int -> !PrimArray Int -> !IORef Storage -> Env (es :: [Effect]) [envOffset] :: Env (es :: [Effect]) -> !Int [envRefs] :: Env (es :: [Effect]) -> !PrimArray Int [envStorage] :: Env (es :: [Effect]) -> !IORef Storage -- | A storage of effects. data Storage Storage :: !Int -> !Int -> !MutablePrimArray RealWorld Int -> !SmallMutableArray RealWorld Any -> !SmallMutableArray RealWorld Any -> Storage [stSize] :: Storage -> !Int [stVersion] :: Storage -> !Int [stVersions] :: Storage -> !MutablePrimArray RealWorld Int [stEffects] :: Storage -> !SmallMutableArray RealWorld Any [stRelinkers] :: Storage -> !SmallMutableArray RealWorld Any -- | A function for relinking Env objects stored in the handlers -- and/or making a deep copy of the representation of the effect when -- cloning the environment. newtype Relinker :: (Effect -> Type) -> Effect -> Type [Relinker] :: ((forall es. Env es -> IO (Env es)) -> rep e -> IO (rep e)) -> Relinker rep e -- | A dummy Relinker. dummyRelinker :: Relinker rep e -- | A type of dispatch. For more information consult the documentation in -- Effectful.Dispatch.Dynamic and -- Effectful.Dispatch.Static. data Dispatch Dynamic :: Dispatch Static :: SideEffects -> Dispatch -- | Signifies whether core operations of a statically dispatched effect -- perform side effects. If an effect is marked as such, the -- runStaticRep family of functions will require the IOE -- effect to be in context via the MaybeIOE type family. data SideEffects NoSideEffects :: SideEffects WithSideEffects :: SideEffects -- | Dispatch types of effects. type family DispatchOf (e :: Effect) :: Dispatch -- | Internal representations of effects. type family EffectRep (d :: Dispatch) :: Effect -> Type -- | Create an empty environment. emptyEnv :: IO (Env '[]) -- | Clone the environment to use it in a different thread. cloneEnv :: Env es -> IO (Env es) -- | Restore the environment from its clone. restoreEnv :: Env es -> Env es -> IO () -- | Get the current size of the environment. sizeEnv :: Env es -> IO Int -- | Access the tail of the environment. tailEnv :: Env (e : es) -> IO (Env es) -- | Extend the environment with a new data type. consEnv :: EffectRep (DispatchOf e) e -> Relinker (EffectRep (DispatchOf e)) e -> Env es -> IO (Env (e : es)) -- | Shrink the environment by one data type. -- -- Note: after calling this function e from the input -- environment is no longer usable. unconsEnv :: Env (e : es) -> IO () -- | Replace a specific effect in the stack with a new value. -- -- Note: unlike in putEnv the value in not changed in -- place, so only the new environment will see it. replaceEnv :: forall e es. e :> es => EffectRep (DispatchOf e) e -> Relinker (EffectRep (DispatchOf e)) e -> Env es -> IO (Env es) -- | Remove a reference to the replaced effect. -- -- Note: after calling this function the input environment is no -- longer usable. unreplaceEnv :: forall e es. e :> es => Env es -> IO () -- | Reference an existing effect from the top of the stack. subsumeEnv :: forall e es. e :> es => Env es -> IO (Env (e : es)) -- | Construct an environment containing a permutation (with possible -- duplicates) of a subset of effects from the input environment. injectEnv :: forall xs es. Subset xs es => Env es -> IO (Env xs) -- | Extract a specific data type from the environment. getEnv :: forall e es. e :> es => Env es -> IO (EffectRep (DispatchOf e) e) -- | Replace the data type in the environment with a new value (in place). putEnv :: forall e es. e :> es => Env es -> EffectRep (DispatchOf e) e -> IO () -- | Modify the data type in the environment and return a value (in place). stateEnv :: forall e es a. e :> es => Env es -> (EffectRep (DispatchOf e) e -> IO (a, EffectRep (DispatchOf e) e)) -> IO a -- | Modify the data type in the environment (in place). modifyEnv :: forall e es. e :> es => Env es -> (EffectRep (DispatchOf e) e -> IO (EffectRep (DispatchOf e) e)) -> IO () -- | Primitive API for statically dispatched effects. -- -- This module exposes internal implementation details of the Eff -- monad. Most of the time functions from -- Effectful.Dispatch.Static are sufficient. -- -- Warning: playing the so called "type tetris" with functions -- from this module is not enough. Their misuse might lead to memory -- corruption or segmentation faults, so make sure you understand what -- you're doing. module Effectful.Dispatch.Static.Primitive -- | A strict (WHNF), thread local, mutable, extensible record -- indexed by types of kind Effect. -- -- Warning: the environment is a mutable data structure and cannot be -- simultaneously used from multiple threads under any circumstances. -- -- In order to pass it to a different thread, you need to perform a deep -- copy with the cloneEnv funtion. -- -- Offers very good performance characteristics for most often performed -- operations: -- -- data Env (es :: [Effect]) -- | A function for relinking Env objects stored in the handlers -- and/or making a deep copy of the representation of the effect when -- cloning the environment. newtype Relinker :: (Effect -> Type) -> Effect -> Type [Relinker] :: ((forall es. Env es -> IO (Env es)) -> rep e -> IO (rep e)) -> Relinker rep e -- | A dummy Relinker. dummyRelinker :: Relinker rep e -- | Internal representations of effects. type family EffectRep (d :: Dispatch) :: Effect -> Type -- | Extend the environment with a new data type. consEnv :: EffectRep (DispatchOf e) e -> Relinker (EffectRep (DispatchOf e)) e -> Env es -> IO (Env (e : es)) -- | Shrink the environment by one data type. -- -- Note: after calling this function e from the input -- environment is no longer usable. unconsEnv :: Env (e : es) -> IO () -- | Extract a specific data type from the environment. getEnv :: forall e es. e :> es => Env es -> IO (EffectRep (DispatchOf e) e) -- | Replace the data type in the environment with a new value (in place). putEnv :: forall e es. e :> es => Env es -> EffectRep (DispatchOf e) e -> IO () -- | Modify the data type in the environment and return a value (in place). stateEnv :: forall e es a. e :> es => Env es -> (EffectRep (DispatchOf e) e -> IO (a, EffectRep (DispatchOf e) e)) -> IO a -- | Modify the data type in the environment (in place). modifyEnv :: forall e es. e :> es => Env es -> (EffectRep (DispatchOf e) e -> IO (EffectRep (DispatchOf e) e)) -> IO () -- | Create an empty environment. emptyEnv :: IO (Env '[]) -- | Clone the environment to use it in a different thread. cloneEnv :: Env es -> IO (Env es) -- | Restore the environment from its clone. restoreEnv :: Env es -> Env es -> IO () -- | Get the current size of the environment. sizeEnv :: Env es -> IO Int -- | Access the tail of the environment. tailEnv :: Env (e : es) -> IO (Env es) -- | Implementation of sequential and concurrent unlifts. -- -- This module is intended for internal use only, and may change without -- warning in subsequent releases. module Effectful.Internal.Unlift -- | The strategy to use when unlifting Eff computations via -- withEffToIO, withRunInIO or the localUnlift -- family. -- -- Note: unlifting functions should not be used outside of -- continuations that brought them into scope. data UnliftStrategy -- | The fastest strategy and a default setting for IOE. An attempt -- to call the unlifting function in threads distinct from its creator -- will result in a runtime error. SeqUnlift :: UnliftStrategy -- | A strategy that makes it possible for the unlifting function to be -- called in threads distinct from its creator. See Persistence -- and Limit settings for more information. ConcUnlift :: !Persistence -> !Limit -> UnliftStrategy -- | Persistence setting for the ConcUnlift strategy. -- -- Different functions require different persistence strategies. -- Examples: -- -- data Persistence -- | Don't persist the environment between calls to the unlifting function -- in threads distinct from its creator. Ephemeral :: Persistence -- | Persist the environment between calls to the unlifting function within -- a particular thread. Persistent :: Persistence -- | Limit setting for the ConcUnlift strategy. data Limit -- | Behavior dependent on the Persistence setting. -- -- For Ephemeral, it limits the amount of uses of the unlifting -- function in threads distinct from its creator to N. The -- unlifting function will create N copies of the environment -- when called N times and K+1 copies when called K -- < N times. -- -- For Persistent, it limits the amount of threads, distinct from -- the creator of the unlifting function, it can be called in to -- N. The amount of calls to the unlifting function within a -- particular threads is unlimited. The unlifting function will create -- N copies of the environment when called in N threads -- and K+1 copies when called in K < N threads. Limited :: !Int -> Limit -- | Unlimited use of the unlifting function. Unlimited :: Limit -- | Sequential unlift. seqUnlift :: HasCallStack => ((forall r. m r -> IO r) -> IO a) -> Env es -> (forall r. m r -> Env es -> IO r) -> IO a -- | Concurrent unlift for various strategies and limits. concUnlift :: HasCallStack => Persistence -> Limit -> ((forall r. m r -> IO r) -> IO a) -> Env es -> (forall r. m r -> Env es -> IO r) -> IO a -- | Concurrent unlift that doesn't preserve the environment between calls -- to the unlifting function in threads other than its creator. ephemeralConcUnlift :: HasCallStack => Int -> ((forall r. m r -> IO r) -> IO a) -> Env es -> (forall r. m r -> Env es -> IO r) -> IO a -- | Concurrent unlift that preserves the environment between calls to the -- unlifting function within a particular thread. persistentConcUnlift :: HasCallStack => Bool -> Int -> ((forall r. m r -> IO r) -> IO a) -> Env es -> (forall r. m r -> Env es -> IO r) -> IO a instance GHC.Show.Show Effectful.Internal.Unlift.Persistence instance GHC.Classes.Ord Effectful.Internal.Unlift.Persistence instance GHC.Generics.Generic Effectful.Internal.Unlift.Persistence instance GHC.Classes.Eq Effectful.Internal.Unlift.Persistence instance GHC.Show.Show Effectful.Internal.Unlift.Limit instance GHC.Classes.Ord Effectful.Internal.Unlift.Limit instance GHC.Generics.Generic Effectful.Internal.Unlift.Limit instance GHC.Classes.Eq Effectful.Internal.Unlift.Limit instance GHC.Show.Show Effectful.Internal.Unlift.UnliftStrategy instance GHC.Classes.Ord Effectful.Internal.Unlift.UnliftStrategy instance GHC.Generics.Generic Effectful.Internal.Unlift.UnliftStrategy instance GHC.Classes.Eq Effectful.Internal.Unlift.UnliftStrategy instance GHC.Classes.Eq Effectful.Internal.Unlift.EntryId -- | The Eff monad. -- -- This module is intended for internal use only, and may change without -- warning in subsequent releases. module Effectful.Internal.Monad -- | The Eff monad provides the implementation of a computation that -- performs an arbitrary set of effects. In Eff es a, -- es is a type-level list that contains all the effects that -- the computation may perform. For example, a computation that produces -- an Integer by consuming a String from the global -- environment and acting upon a single mutable value of type Bool -- would have the following type: -- --
--   (Reader String :> es, State Bool :> es) => Eff es Integer
--   
-- -- Abstracting over the list of effects with (:>): -- -- data Eff (es :: [Effect]) a -- | Run a pure Eff computation. -- -- For running computations with side effects see runEff. runPureEff :: Eff '[] a -> a -- | Peel off the constructor of Eff. unEff :: Eff es a -> Env es -> IO a -- | Access the underlying IO monad along with the environment. -- -- This function is unsafe because it can be used to introduce -- arbitrary IO actions into pure Eff computations. unsafeEff :: (Env es -> IO a) -> Eff es a -- | Access the underlying IO monad. -- -- This function is unsafe because it can be used to introduce -- arbitrary IO actions into pure Eff computations. unsafeEff_ :: IO a -> Eff es a -- | Provide the ability to use the Alternative and MonadPlus -- instance of Eff. data NonDet :: Effect [Empty] :: NonDet m a [:<|>:] :: m a -> m a -> NonDet m a -- | Provide the ability to use the MonadFail instance of -- Eff. data Fail :: Effect [Fail] :: String -> Fail m a -- | Run arbitrary IO computations via MonadIO or -- MonadUnliftIO. -- -- Note: it is not recommended to use this effect in application -- code as it is too liberal. Ideally, this is only used in handlers of -- more fine-grained effects. data IOE :: Effect -- | Run an Eff computation with side effects. -- -- For running pure computations see runPureEff. runEff :: Eff '[IOE] a -> IO a -- | Provide the ability to perform primitive state-transformer actions. data Prim :: Effect -- | PrimState token for Eff. Used instead of -- RealWorld to prevent the Prim effect from executing -- arbitrary IO actions via ioToPrim. data PrimStateEff -- | Run an Eff computation with primitive state-transformer -- actions. runPrim :: IOE :> es => Eff (Prim : es) a -> Eff es a -- | Lift an Eff computation into an effect stack with one more -- effect. raise :: Eff es a -> Eff (e : es) a -- | Lift an Eff computation into an effect stack with one more -- effect and create an unlifting function with the given strategy. raiseWith :: HasCallStack => UnliftStrategy -> ((forall r. Eff (e : es) r -> Eff es r) -> Eff es a) -> Eff (e : es) a -- | Eliminate a duplicate effect from the top of the effect stack. subsume :: e :> es => Eff (e : es) a -> Eff es a -- | Allow for running an effect stack xs within es as -- long as xs is a permutation (with possible duplicates) of a -- subset of es. -- -- Generalizes raise and subsume. -- -- Note: this function should be needed rarely, usually when you -- have to cross API boundaries and monomorphic effect stacks are -- involved. Using monomorphic stacks is discouraged (see Eff), -- but sometimes might be necessary due to external constraints. inject :: Subset xs es => Eff xs a -> Eff es a -- | The strategy to use when unlifting Eff computations via -- withEffToIO, withRunInIO or the localUnlift -- family. -- -- Note: unlifting functions should not be used outside of -- continuations that brought them into scope. data UnliftStrategy -- | The fastest strategy and a default setting for IOE. An attempt -- to call the unlifting function in threads distinct from its creator -- will result in a runtime error. SeqUnlift :: UnliftStrategy -- | A strategy that makes it possible for the unlifting function to be -- called in threads distinct from its creator. See Persistence -- and Limit settings for more information. ConcUnlift :: !Persistence -> !Limit -> UnliftStrategy -- | Persistence setting for the ConcUnlift strategy. -- -- Different functions require different persistence strategies. -- Examples: -- -- data Persistence -- | Don't persist the environment between calls to the unlifting function -- in threads distinct from its creator. Ephemeral :: Persistence -- | Persist the environment between calls to the unlifting function within -- a particular thread. Persistent :: Persistence -- | Limit setting for the ConcUnlift strategy. data Limit -- | Behavior dependent on the Persistence setting. -- -- For Ephemeral, it limits the amount of uses of the unlifting -- function in threads distinct from its creator to N. The -- unlifting function will create N copies of the environment -- when called N times and K+1 copies when called K -- < N times. -- -- For Persistent, it limits the amount of threads, distinct from -- the creator of the unlifting function, it can be called in to -- N. The amount of calls to the unlifting function within a -- particular threads is unlimited. The unlifting function will create -- N copies of the environment when called in N threads -- and K+1 copies when called in K < N threads. Limited :: !Int -> Limit -- | Unlimited use of the unlifting function. Unlimited :: Limit -- | Get the current UnliftStrategy. unliftStrategy :: IOE :> es => Eff es UnliftStrategy -- | Locally override the UnliftStrategy with the given value. withUnliftStrategy :: IOE :> es => UnliftStrategy -> Eff es a -> Eff es a -- | Create an unlifting function with the current UnliftStrategy. -- -- This function is equivalent to withRunInIO, but has a -- HasCallStack constraint for accurate stack traces in case an -- insufficiently powerful UnliftStrategy is used and the -- unlifting function fails. withEffToIO :: (HasCallStack, IOE :> es) => ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a -- | Create an unlifting function with the SeqUnlift strategy. seqUnliftIO :: HasCallStack => Env es -> ((forall r. Eff es r -> IO r) -> IO a) -> IO a -- | Create an unlifting function with the ConcUnlift strategy. concUnliftIO :: HasCallStack => Env es -> Persistence -> Limit -> ((forall r. Eff es r -> IO r) -> IO a) -> IO a -- | Type signature of the effect handler. type EffectHandler e es = forall a localEs. (HasCallStack, e :> localEs) => LocalEnv localEs es " Capture of the local environment for handling local 'Eff' computations when @e@ is a higher order effect." -> e (Eff localEs) a " The effect performed in the local environment." -> Eff es a -- | Opaque representation of the Eff environment at the point of -- calling the send function, i.e. right before the control is -- passed to the effect handler. -- -- The second type variable represents effects of a handler and is needed -- for technical reasons to guarantee soundness (see SharedSuffix -- for more information). newtype LocalEnv (localEs :: [Effect]) (handlerEs :: [Effect]) LocalEnv :: Env localEs -> LocalEnv (localEs :: [Effect]) (handlerEs :: [Effect]) -- | An internal representation of dynamically dispatched effects, i.e. the -- effect handler bundled with its environment. data Handler :: Effect -> Type [Handler] :: !Env es -> !EffectHandler e es -> Handler e relinkHandler :: Relinker Handler e -- | Run a dynamically dispatched effect with the given handler. runHandler :: DispatchOf e ~ Dynamic => Handler e -> Eff (e : es) a -> Eff es a -- | Send an operation of the given effect to its handler for execution. send :: (HasCallStack, DispatchOf e ~ Dynamic, e :> es) => e (Eff es) a -> Eff es a -- | Internal representations of statically dispatched effects. data family StaticRep (e :: Effect) :: Type -- | Require the IOE effect for running statically dispatched -- effects whose operations perform side effects. type family MaybeIOE (sideEffects :: SideEffects) (es :: [Effect]) :: Constraint -- | Run a statically dispatched effect with the given initial -- representation and return the final value along with the final -- representation. runStaticRep :: (DispatchOf e ~ Static sideEffects, MaybeIOE sideEffects es) => StaticRep e -> Eff (e : es) a -> Eff es (a, StaticRep e) -- | Run a statically dispatched effect with the given initial -- representation and return the final value, discarding the final -- representation. evalStaticRep :: (DispatchOf e ~ Static sideEffects, MaybeIOE sideEffects es) => StaticRep e -> Eff (e : es) a -> Eff es a -- | Run a statically dispatched effect with the given initial -- representation and return the final representation, discarding the -- final value. execStaticRep :: (DispatchOf e ~ Static sideEffects, MaybeIOE sideEffects es) => StaticRep e -> Eff (e : es) a -> Eff es (StaticRep e) -- | Fetch the current representation of the effect. getStaticRep :: (DispatchOf e ~ Static sideEffects, e :> es) => Eff es (StaticRep e) -- | Set the current representation of the effect to the given value. putStaticRep :: (DispatchOf e ~ Static sideEffects, e :> es) => StaticRep e -> Eff es () -- | Apply the function to the current representation of the effect and -- return a value. stateStaticRep :: (DispatchOf e ~ Static sideEffects, e :> es) => (StaticRep e -> (a, StaticRep e)) -> Eff es a -- | Apply the monadic function to the current representation of the effect -- and return a value. stateStaticRepM :: (DispatchOf e ~ Static sideEffects, e :> es) => (StaticRep e -> Eff es (a, StaticRep e)) -> Eff es a -- | Execute a computation with a temporarily modified representation of -- the effect. localStaticRep :: (DispatchOf e ~ Static sideEffects, e :> es) => (StaticRep e -> StaticRep e) -> Eff es a -> Eff es a -- | Extend the environment with a new data type. consEnv :: EffectRep (DispatchOf e) e -> Relinker (EffectRep (DispatchOf e)) e -> Env es -> IO (Env (e : es)) -- | Extract a specific data type from the environment. getEnv :: forall e es. e :> es => Env es -> IO (EffectRep (DispatchOf e) e) -- | Replace the data type in the environment with a new value (in place). putEnv :: forall e es. e :> es => Env es -> EffectRep (DispatchOf e) e -> IO () -- | Modify the data type in the environment and return a value (in place). stateEnv :: forall e es a. e :> es => Env es -> (EffectRep (DispatchOf e) e -> IO (a, EffectRep (DispatchOf e) e)) -> IO a -- | Modify the data type in the environment (in place). modifyEnv :: forall e es. e :> es => Env es -> (EffectRep (DispatchOf e) e -> IO (EffectRep (DispatchOf e) e)) -> IO () instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Effectful.Internal.Monad.Eff es a) instance GHC.Base.Monoid a => GHC.Base.Monoid (Effectful.Internal.Monad.Eff es a) instance (Effectful.Internal.Monad.Prim Effectful.Internal.Effect.:> es) => Control.Monad.Primitive.PrimMonad (Effectful.Internal.Monad.Eff es) instance (Effectful.Internal.Monad.IOE Effectful.Internal.Effect.:> es) => Control.Monad.IO.Class.MonadIO (Effectful.Internal.Monad.Eff es) instance (Effectful.Internal.Monad.IOE Effectful.Internal.Effect.:> es) => Control.Monad.IO.Unlift.MonadUnliftIO (Effectful.Internal.Monad.Eff es) instance (Effectful.Internal.Monad.IOE Effectful.Internal.Effect.:> es) => Control.Monad.Base.MonadBase GHC.Types.IO (Effectful.Internal.Monad.Eff es) instance (Effectful.Internal.Monad.IOE Effectful.Internal.Effect.:> es) => Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO (Effectful.Internal.Monad.Eff es) instance (Effectful.Internal.Monad.Fail Effectful.Internal.Effect.:> es) => Control.Monad.Fail.MonadFail (Effectful.Internal.Monad.Eff es) instance (Effectful.Internal.Monad.NonDet Effectful.Internal.Effect.:> es) => GHC.Base.Alternative (Effectful.Internal.Monad.Eff es) instance (Effectful.Internal.Monad.NonDet Effectful.Internal.Effect.:> es) => GHC.Base.MonadPlus (Effectful.Internal.Monad.Eff es) instance GHC.Base.Functor (Effectful.Internal.Monad.Eff es) instance GHC.Base.Applicative (Effectful.Internal.Monad.Eff es) instance GHC.Base.Monad (Effectful.Internal.Monad.Eff es) instance Control.Monad.Fix.MonadFix (Effectful.Internal.Monad.Eff es) instance Control.Monad.Catch.MonadThrow (Effectful.Internal.Monad.Eff es) instance Control.Monad.Catch.MonadCatch (Effectful.Internal.Monad.Eff es) instance Control.Monad.Catch.MonadMask (Effectful.Internal.Monad.Eff es) -- | Unsafe utilities for statically dispatched effects. module Effectful.Dispatch.Static.Unsafe -- | Utility for lifting IO computations of type -- --
--   IO a -> IO b
--   
-- -- to -- --
--   Eff es a -> Eff es b
--   
-- -- This function is highly unsafe because: -- -- -- -- If you disregard the second point, segmentation faults await. reallyUnsafeLiftMapIO :: (IO a -> IO b) -> Eff es a -> Eff es b -- | Create an unlifting function. -- -- This function is highly unsafe because: -- -- -- -- If you disregard the second point, segmentation faults await. reallyUnsafeUnliftIO :: ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a -- | Statically dispatched effects. module Effectful.Dispatch.Static -- | Internal representations of statically dispatched effects. data family StaticRep (e :: Effect) :: Type -- | Signifies whether core operations of a statically dispatched effect -- perform side effects. If an effect is marked as such, the -- runStaticRep family of functions will require the IOE -- effect to be in context via the MaybeIOE type family. data SideEffects NoSideEffects :: SideEffects WithSideEffects :: SideEffects -- | Require the IOE effect for running statically dispatched -- effects whose operations perform side effects. type family MaybeIOE (sideEffects :: SideEffects) (es :: [Effect]) :: Constraint -- | Run a statically dispatched effect with the given initial -- representation and return the final value along with the final -- representation. runStaticRep :: (DispatchOf e ~ Static sideEffects, MaybeIOE sideEffects es) => StaticRep e -> Eff (e : es) a -> Eff es (a, StaticRep e) -- | Run a statically dispatched effect with the given initial -- representation and return the final value, discarding the final -- representation. evalStaticRep :: (DispatchOf e ~ Static sideEffects, MaybeIOE sideEffects es) => StaticRep e -> Eff (e : es) a -> Eff es a -- | Run a statically dispatched effect with the given initial -- representation and return the final representation, discarding the -- final value. execStaticRep :: (DispatchOf e ~ Static sideEffects, MaybeIOE sideEffects es) => StaticRep e -> Eff (e : es) a -> Eff es (StaticRep e) -- | Fetch the current representation of the effect. getStaticRep :: (DispatchOf e ~ Static sideEffects, e :> es) => Eff es (StaticRep e) -- | Set the current representation of the effect to the given value. putStaticRep :: (DispatchOf e ~ Static sideEffects, e :> es) => StaticRep e -> Eff es () -- | Apply the function to the current representation of the effect and -- return a value. stateStaticRep :: (DispatchOf e ~ Static sideEffects, e :> es) => (StaticRep e -> (a, StaticRep e)) -> Eff es a -- | Apply the monadic function to the current representation of the effect -- and return a value. stateStaticRepM :: (DispatchOf e ~ Static sideEffects, e :> es) => (StaticRep e -> Eff es (a, StaticRep e)) -> Eff es a -- | Execute a computation with a temporarily modified representation of -- the effect. localStaticRep :: (DispatchOf e ~ Static sideEffects, e :> es) => (StaticRep e -> StaticRep e) -> Eff es a -> Eff es a -- | Create an unlifting function with the SeqUnlift strategy. seqUnliftIO :: HasCallStack => Env es -> ((forall r. Eff es r -> IO r) -> IO a) -> IO a -- | Create an unlifting function with the ConcUnlift strategy. concUnliftIO :: HasCallStack => Env es -> Persistence -> Limit -> ((forall r. Eff es r -> IO r) -> IO a) -> IO a -- | Create an unlifting function with the SeqUnlift strategy. -- -- This function is unsafe because it can be used to introduce -- arbitrary IO actions into pure Eff computations. unsafeSeqUnliftIO :: HasCallStack => ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a -- | Create an unlifting function with the ConcUnlift strategy. -- -- This function is unsafe because it can be used to introduce -- arbitrary IO actions into pure Eff computations. unsafeConcUnliftIO :: HasCallStack => Persistence -> Limit -> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a -- | Peel off the constructor of Eff. unEff :: Eff es a -> Env es -> IO a -- | Access the underlying IO monad along with the environment. -- -- This function is unsafe because it can be used to introduce -- arbitrary IO actions into pure Eff computations. unsafeEff :: (Env es -> IO a) -> Eff es a -- | Access the underlying IO monad. -- -- This function is unsafe because it can be used to introduce -- arbitrary IO actions into pure Eff computations. unsafeEff_ :: IO a -> Eff es a -- | Utility for lifting IO computations of type -- --
--   IO a -> IO b
--   
-- -- to -- --
--   Eff es a -> Eff es b
--   
-- -- Note: the computation must not run its argument in a separate -- thread, attempting to do so will result in a runtime error. -- -- This function is unsafe because it can be used to introduce -- arbitrary IO actions into pure Eff computations. unsafeLiftMapIO :: HasCallStack => (IO a -> IO b) -> Eff es a -> Eff es b -- | Request a CallStack. -- -- NOTE: The implicit parameter ?callStack :: CallStack is an -- implementation detail and should not be considered part of the -- CallStack API, we may decide to change the implementation in -- the future. type HasCallStack = ?callStack :: CallStack -- | Dynamically dispatched effects. module Effectful.Dispatch.Dynamic -- | Send an operation of the given effect to its handler for execution. send :: (HasCallStack, DispatchOf e ~ Dynamic, e :> es) => e (Eff es) a -> Eff es a -- | Type signature of the effect handler. type EffectHandler e es = forall a localEs. (HasCallStack, e :> localEs) => LocalEnv localEs es " Capture of the local environment for handling local 'Eff' computations when @e@ is a higher order effect." -> e (Eff localEs) a " The effect performed in the local environment." -> Eff es a -- | Interpret an effect. interpret :: DispatchOf e ~ Dynamic => EffectHandler e es -> Eff (e : es) a -> Eff es a -- | Interpret an effect using other, private effects. -- --
--   interpretreinterpret id
--   
reinterpret :: DispatchOf e ~ Dynamic => (Eff handlerEs a -> Eff es b) -> EffectHandler e handlerEs -> Eff (e : es) a -> Eff es b -- | Replace the handler of an existing effect with a new one. -- -- Note: this function allows for augmenting handlers with a new -- functionality as the new handler can send operations to the old one. -- --
--   >>> :{
--     data E :: Effect where
--       Op :: E m ()
--     type instance DispatchOf E = Dynamic
--   :}
--   
-- --
--   >>> :{
--     runE :: IOE :> es => Eff (E : es) a -> Eff es a
--     runE = interpret $ \_ Op -> liftIO (putStrLn "op")
--   :}
--   
-- --
--   >>> runEff . runE $ send Op
--   op
--   
-- --
--   >>> :{
--     augmentE :: (E :> es, IOE :> es) => Eff es a -> Eff es a
--     augmentE = interpose $ \_ Op -> liftIO (putStrLn "augmented op") >> send Op
--   :}
--   
-- --
--   >>> runEff . runE . augmentE $ send Op
--   augmented op
--   op
--   
interpose :: forall e es a. (DispatchOf e ~ Dynamic, e :> es) => EffectHandler e es -> Eff es a -> Eff es a -- | Replace the handler of an existing effect with a new one that uses -- other, private effects. -- --
--   interposeimpose id
--   
impose :: forall e es handlerEs a b. (DispatchOf e ~ Dynamic, e :> es) => (Eff handlerEs a -> Eff es b) -> EffectHandler e handlerEs -> Eff es a -> Eff es b -- | Opaque representation of the Eff environment at the point of -- calling the send function, i.e. right before the control is -- passed to the effect handler. -- -- The second type variable represents effects of a handler and is needed -- for technical reasons to guarantee soundness (see SharedSuffix -- for more information). data LocalEnv (localEs :: [Effect]) (handlerEs :: [Effect]) -- | Create a local unlifting function with the SeqUnlift strategy. -- For the general version see localUnlift. localSeqUnlift :: (HasCallStack, SharedSuffix es handlerEs) => LocalEnv localEs handlerEs -> ((forall r. Eff localEs r -> Eff es r) -> Eff es a) -> Eff es a -- | Create a local unlifting function with the SeqUnlift strategy. -- For the general version see localUnliftIO. localSeqUnliftIO :: (HasCallStack, SharedSuffix es handlerEs, IOE :> es) => LocalEnv localEs handlerEs -> ((forall r. Eff localEs r -> IO r) -> IO a) -> Eff es a -- | Create a local unlifting function with the given strategy. localUnlift :: (HasCallStack, SharedSuffix es handlerEs) => LocalEnv localEs handlerEs -> UnliftStrategy -> ((forall r. Eff localEs r -> Eff es r) -> Eff es a) -> Eff es a -- | Create a local unlifting function with the given strategy. localUnliftIO :: (HasCallStack, SharedSuffix es handlerEs, IOE :> es) => LocalEnv localEs handlerEs -> UnliftStrategy -> ((forall r. Eff localEs r -> IO r) -> IO a) -> Eff es a -- | Utility for lifting Eff computations of type -- --
--   Eff es a -> Eff es b
--   
-- -- to -- --
--   Eff localEs a -> Eff localEs b
--   
-- -- Note: the computation must not run its argument in a different -- thread, attempting to do so will result in a runtime error. withLiftMap :: (HasCallStack, SharedSuffix es handlerEs) => LocalEnv localEs handlerEs -> ((forall a b. (Eff es a -> Eff es b) -> Eff localEs a -> Eff localEs b) -> Eff es r) -> Eff es r -- | Utility for lifting IO computations of type -- --
--   IO a -> IO b
--   
-- -- to -- --
--   Eff localEs a -> Eff localEs b
--   
-- -- Note: the computation must not run its argument in a different -- thread, attempting to do so will result in a runtime error. -- -- Useful e.g. for lifting the unmasking function in mask-like -- computations: -- --
--   >>> :{
--   data Fork :: Effect where
--     ForkWithUnmask :: ((forall a. m a -> m a) -> m ()) -> Fork m ThreadId
--   type instance DispatchOf Fork = Dynamic
--   :}
--   
-- --
--   >>> :{
--   runFork :: IOE :> es => Eff (Fork : es) a -> Eff es a
--   runFork = interpret $ \env (ForkWithUnmask m) -> withLiftMapIO env $ \liftMap -> do
--     localUnliftIO env (ConcUnlift Ephemeral $ Limited 1) $ \unlift -> do
--       forkIOWithUnmask $ \unmask -> unlift $ m $ liftMap unmask
--   :}
--   
withLiftMapIO :: (HasCallStack, SharedSuffix es handlerEs, IOE :> es) => LocalEnv localEs handlerEs -> ((forall a b. (IO a -> IO b) -> Eff localEs a -> Eff localEs b) -> Eff es r) -> Eff es r -- | Create a local lifting and unlifting function with the given strategy. -- -- Useful for lifting complicated Eff computations where the -- monadic action shows in both positive (as a result) and negative (as -- an argument) position. -- -- Note: depending on the computation you're lifting -- localUnlift along with withLiftMap might be enough and -- is more efficient. localLiftUnlift :: (HasCallStack, SharedSuffix es handlerEs) => LocalEnv localEs handlerEs -> UnliftStrategy -> ((forall r. Eff es r -> Eff localEs r) -> (forall r. Eff localEs r -> Eff es r) -> Eff es a) -> Eff es a -- | Create a local unlifting function with the given strategy along with -- an unrestricted lifting function. -- -- Useful for lifting complicated IO computations where the -- monadic action shows in both positive (as a result) and negative (as -- an argument) position. -- -- Note: depending on the computation you're lifting -- localUnliftIO along with withLiftMapIO might be enough -- and is more efficient. localLiftUnliftIO :: (HasCallStack, SharedSuffix es handlerEs, IOE :> es) => LocalEnv localEs handlerEs -> UnliftStrategy -> ((forall r. IO r -> Eff localEs r) -> (forall r. Eff localEs r -> IO r) -> IO a) -> Eff es a -- | Require that both effect stacks share an opaque suffix. -- -- Functions from the localUnlift family utilize this constraint -- to guarantee sensible usage of unlifting functions. -- -- As an example, consider the following higher order effect: -- --
--   >>> :{
--     data E :: Effect where
--       E :: m a -> E m a
--     type instance DispatchOf E = Dynamic
--   :}
--   
-- -- Running local actions in a more specific environment is fine: -- --
--   >>> :{
--    runE1 :: Eff (E ': es) a -> Eff es a
--    runE1 = interpret $ \env -> \case
--      E m -> runReader () $ do
--        localSeqUnlift env $ \unlift -> unlift m
--   :}
--   
-- -- Running local actions in a more general environment is fine: -- --
--   >>> :{
--    runE2 :: Eff (E ': es) a -> Eff es a
--    runE2 = reinterpret (runReader ()) $ \env -> \case
--      E m -> raise $ do
--        localSeqUnlift env $ \unlift -> unlift m
--   :}
--   
-- -- However, running local actions in an unrelated environment is not fine -- as this would make it possible to run anything within -- runPureEff: -- --
--   >>> :{
--    runE3 :: Eff (E ': es) a -> Eff es a
--    runE3 = reinterpret (runReader ()) $ \env -> \case
--      E m -> pure . runPureEff $ do
--        localSeqUnlift env $ \unlift -> unlift m
--   :}
--   ...
--   ...Could not deduce (SharedSuffix '[] es)...
--   ...
--   
-- -- Running local actions in a monomorphic effect stack is also not fine -- as this makes a special case of the above possible: -- --
--   >>> :{
--    runE4 :: Eff '[E, IOE] a -> Eff '[IOE] a
--    runE4 = interpret $ \env -> \case
--      E m -> pure . runPureEff $ do
--        localSeqUnlift env $ \unlift -> unlift m
--   :}
--   ...
--   ...Running local actions in monomorphic effect stacks is not supported...
--   ...
--   
class SharedSuffix (es1 :: [Effect]) (es2 :: [Effect]) -- | Request a CallStack. -- -- NOTE: The implicit parameter ?callStack :: CallStack is an -- implementation detail and should not be considered part of the -- CallStack API, we may decide to change the implementation in -- the future. type HasCallStack = ?callStack :: CallStack instance Effectful.Dispatch.Dynamic.SharedSuffix es es instance Effectful.Dispatch.Dynamic.SharedSuffix es1 es2 => Effectful.Dispatch.Dynamic.SharedSuffix (e : es1) es2 instance Effectful.Dispatch.Dynamic.SharedSuffix es1 es2 => Effectful.Dispatch.Dynamic.SharedSuffix es1 (e : es2) instance (TypeError ...) => Effectful.Dispatch.Dynamic.SharedSuffix '[] '[] module Effectful -- | The Eff monad provides the implementation of a computation that -- performs an arbitrary set of effects. In Eff es a, -- es is a type-level list that contains all the effects that -- the computation may perform. For example, a computation that produces -- an Integer by consuming a String from the global -- environment and acting upon a single mutable value of type Bool -- would have the following type: -- --
--   (Reader String :> es, State Bool :> es) => Eff es Integer
--   
-- -- Abstracting over the list of effects with (:>): -- -- data Eff (es :: [Effect]) a -- | The kind of effects. type Effect = (Type -> Type) -> Type -> Type -- | A type of dispatch. For more information consult the documentation in -- Effectful.Dispatch.Dynamic and -- Effectful.Dispatch.Static. data Dispatch Dynamic :: Dispatch Static :: SideEffects -> Dispatch -- | Dispatch types of effects. type family DispatchOf (e :: Effect) :: Dispatch -- | A constraint that requires that a particular effect e is a -- member of the type-level list es. This is used to -- parameterize an Eff computation over an arbitrary list of -- effects, so long as e is somewhere in the list. -- -- For example, a computation that only needs access to a mutable value -- of type Integer would have the following type: -- --
--   State Integer :> es => Eff es ()
--   
class (e :: Effect) :> (es :: [Effect]) -- | Convenience operator for expressing that a function uses multiple -- effects in a more concise way than enumerating them all with -- (:>). -- --
--   [E1, E2, ..., En] :>> es ≡ (E1 :> es, E2 :> es, ..., En :> es)
--   
-- | Deprecated: Usage of (:>>) slows down GHC too much, so it -- will be removed in 3.0.0.0. See -- https://github.com/haskell-effectful/effectful/issues/52#issuecomment-1269155485 -- for more information. type family xs :>> es :: Constraint -- | Run a pure Eff computation. -- -- For running computations with side effects see runEff. runPureEff :: Eff '[] a -> a -- | Run an Eff computation with side effects. -- -- For running pure computations see runPureEff. runEff :: Eff '[IOE] a -> IO a -- | Run arbitrary IO computations via MonadIO or -- MonadUnliftIO. -- -- Note: it is not recommended to use this effect in application -- code as it is too liberal. Ideally, this is only used in handlers of -- more fine-grained effects. data IOE :: Effect -- | The strategy to use when unlifting Eff computations via -- withEffToIO, withRunInIO or the localUnlift -- family. -- -- Note: unlifting functions should not be used outside of -- continuations that brought them into scope. data UnliftStrategy -- | The fastest strategy and a default setting for IOE. An attempt -- to call the unlifting function in threads distinct from its creator -- will result in a runtime error. SeqUnlift :: UnliftStrategy -- | A strategy that makes it possible for the unlifting function to be -- called in threads distinct from its creator. See Persistence -- and Limit settings for more information. ConcUnlift :: !Persistence -> !Limit -> UnliftStrategy -- | Persistence setting for the ConcUnlift strategy. -- -- Different functions require different persistence strategies. -- Examples: -- -- data Persistence -- | Don't persist the environment between calls to the unlifting function -- in threads distinct from its creator. Ephemeral :: Persistence -- | Persist the environment between calls to the unlifting function within -- a particular thread. Persistent :: Persistence -- | Limit setting for the ConcUnlift strategy. data Limit -- | Behavior dependent on the Persistence setting. -- -- For Ephemeral, it limits the amount of uses of the unlifting -- function in threads distinct from its creator to N. The -- unlifting function will create N copies of the environment -- when called N times and K+1 copies when called K -- < N times. -- -- For Persistent, it limits the amount of threads, distinct from -- the creator of the unlifting function, it can be called in to -- N. The amount of calls to the unlifting function within a -- particular threads is unlimited. The unlifting function will create -- N copies of the environment when called in N threads -- and K+1 copies when called in K < N threads. Limited :: !Int -> Limit -- | Unlimited use of the unlifting function. Unlimited :: Limit -- | Get the current UnliftStrategy. unliftStrategy :: IOE :> es => Eff es UnliftStrategy -- | Locally override the UnliftStrategy with the given value. withUnliftStrategy :: IOE :> es => UnliftStrategy -> Eff es a -> Eff es a -- | Create an unlifting function with the current UnliftStrategy. -- -- This function is equivalent to withRunInIO, but has a -- HasCallStack constraint for accurate stack traces in case an -- insufficiently powerful UnliftStrategy is used and the -- unlifting function fails. withEffToIO :: (HasCallStack, IOE :> es) => ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a -- | Lift an Eff computation into an effect stack with one more -- effect. raise :: Eff es a -> Eff (e : es) a -- | Lift an Eff computation into an effect stack with one more -- effect and create an unlifting function with the given strategy. raiseWith :: HasCallStack => UnliftStrategy -> ((forall r. Eff (e : es) r -> Eff es r) -> Eff es a) -> Eff (e : es) a -- | Eliminate a duplicate effect from the top of the effect stack. subsume :: e :> es => Eff (e : es) a -> Eff es a -- | Allow for running an effect stack xs within es as -- long as xs is a permutation (with possible duplicates) of a -- subset of es. -- -- Generalizes raise and subsume. -- -- Note: this function should be needed rarely, usually when you -- have to cross API boundaries and monomorphic effect stacks are -- involved. Using monomorphic stacks is discouraged (see Eff), -- but sometimes might be necessary due to external constraints. inject :: Subset xs es => Eff xs a -> Eff es a -- | Provide evidence that xs is a subset of es. class Subset (xs :: [Effect]) (es :: [Effect]) -- | 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. This allows us to run IO -- computations in any monadic stack, so long as it supports these kinds -- of operations (i.e. IO is the base monad for the stack). -- --

Example

-- --
--   import Control.Monad.Trans.State -- from the "transformers" library
--   
--   printState :: Show s => StateT s IO ()
--   printState = do
--     state <- get
--     liftIO $ print state
--   
-- -- Had we omitted liftIO, we would have ended up with -- this error: -- --
--   • Couldn't match type ‘IO’ with ‘StateT s IO’
--    Expected type: StateT s IO ()
--      Actual type: IO ()
--   
-- -- The important part here is the mismatch between StateT s IO -- () and IO (). -- -- Luckily, we know of a function that takes an IO a and -- returns an (m a): liftIO, enabling us to run -- the program and see the expected results: -- --
--   > evalStateT printState "hello"
--   "hello"
--   
--   > evalStateT printState 3
--   3
--   
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: -- -- -- -- Instances of MonadUnliftIO must also satisfy the idempotency -- law: -- -- -- -- This law showcases two properties. First, askUnliftIO doesn't -- change the monadic context, and second, liftIO . unliftIO u -- is equivalent to id IF called in the same monadic context as -- askUnliftIO. class MonadIO m => MonadUnliftIO (m :: Type -> Type) -- | Convenience function for capturing the monadic context and running an -- IO action with a runner function. The runner function is used -- to run a monadic action m in IO. withRunInIO :: MonadUnliftIO m => ((forall a. () => m a -> IO a) -> IO b) -> m b -- | Support for handling errors of a particular type, i.e. checked -- exceptions. -- -- The Error effect is not a general mechanism for handling -- regular exceptions, that's what functions from the exceptions -- library are for (see Control.Monad.Catch for more information). -- -- In particular, regular exceptions of type e are distinct from -- errors of type e and will not be caught by functions -- from this module: -- --
--   >>> import qualified Control.Monad.Catch as E
--   
-- --
--   >>> boom = error "BOOM!"
--   
-- --
--   >>> runEff . runError @ErrorCall $ boom `catchError` \_ (_::ErrorCall) -> pure "caught"
--   *** Exception: BOOM!
--   ...
--   
-- -- If you want to catch regular exceptions, you should use catch -- (or a similar function): -- --
--   >>> runEff $ boom `E.catch` \(_::ErrorCall) -> pure "caught"
--   "caught"
--   
-- -- On the other hand, functions for safe finalization and management of -- resources such as finally and bracket work as expected: -- --
--   >>> msg = liftIO . putStrLn
--   
-- --
--   >>> :{
--   runEff . runErrorNoCallStack @String $ do
--     E.bracket_ (msg "Beginning.")
--                (msg "Cleaning up.")
--                (msg "Computing." >> throwError "oops" >> msg "More.")
--   :}
--   Beginning.
--   Computing.
--   Cleaning up.
--   Left "oops"
--   
-- -- Note: unlike the ExceptT monad transformer from the -- transformers library, the order in which you handle the -- Error effect with regard to other stateful effects does not -- matter. Consider the following: -- --
--   >>> import qualified Control.Monad.State.Strict as T
--   
--   >>> import qualified Control.Monad.Except as T
--   
-- --
--   >>> m1 = (T.modify (++ " there!") >> T.throwError "oops") `T.catchError` \_ -> pure ()
--   
-- --
--   >>> (`T.runStateT` "Hi") . T.runExceptT $ m1
--   (Right (),"Hi there!")
--   
-- --
--   >>> T.runExceptT . (`T.runStateT` "Hi") $ m1
--   Right ((),"Hi")
--   
-- -- Here, whether state updates within the catchError block are -- discarded or not depends on the shape of the monad transformer stack, -- which is surprising and can be a source of subtle bugs. On the other -- hand: -- --
--   >>> import Effectful.State.Static.Local
--   
-- --
--   >>> m2 = (modify (++ " there!") >> throwError "oops") `catchError` \_ (_::String) -> pure ()
--   
-- --
--   >>> runEff . runState "Hi" . runError @String $ m2
--   (Right (),"Hi there!")
--   
-- --
--   >>> runEff . runError @String . runState "Hi" $ m2
--   Right ((),"Hi there!")
--   
-- -- Here, no matter the order of effects, state updates made within the -- catchError block before the error happens always persist, -- giving predictable behavior. -- -- Hint: if you'd like to reproduce the transactional behavior -- with the State effect, appropriate usage of -- bracketOnError will do the trick. module Effectful.Error.Static -- | Provide the ability to handle errors of type e. data Error e :: Effect -- | Handle errors of type e. runError :: forall e es a. Eff (Error e : es) a -> Eff es (Either (CallStack, e) a) -- | Handle errors of type e. In case of an error discard the -- CallStack. runErrorNoCallStack :: forall e es a. Eff (Error e : es) a -> Eff es (Either e a) -- | Throw an error of type e. throwError :: forall e es a. (HasCallStack, Error e :> es) => e -> Eff es a -- | Handle an error of type e. catchError :: forall e es a. Error e :> es => Eff es a -> (CallStack -> e -> Eff es a) -> Eff es a -- | The same as flip catchError, which is useful in -- situations where the code for the handler is shorter. handleError :: forall e es a. Error e :> es => (CallStack -> e -> Eff es a) -> Eff es a -> Eff es a -- | Similar to catchError, but returns an Either result -- which is a Right if no error was thrown and a Left -- otherwise. tryError :: forall e es a. Error e :> es => Eff es a -> Eff es (Either (CallStack, e) a) -- | Request a CallStack. -- -- NOTE: The implicit parameter ?callStack :: CallStack is an -- implementation detail and should not be considered part of the -- CallStack API, we may decide to change the implementation in -- the future. type HasCallStack = ?callStack :: CallStack -- | CallStacks are a lightweight method of obtaining a partial -- call-stack at any point in the program. -- -- A function can request its call-site with the HasCallStack -- constraint. For example, we can define -- --
--   putStrLnWithCallStack :: HasCallStack => String -> IO ()
--   
-- -- as a variant of putStrLn that will get its call-site and -- print it, along with the string given as argument. We can access the -- call-stack inside putStrLnWithCallStack with -- callStack. -- --
--   >>> :{
--   putStrLnWithCallStack :: HasCallStack => String -> IO ()
--   putStrLnWithCallStack msg = do
--     putStrLn msg
--     putStrLn (prettyCallStack callStack)
--   :}
--   
-- -- Thus, if we call putStrLnWithCallStack we will get a -- formatted call-stack alongside our string. -- --
--   >>> putStrLnWithCallStack "hello"
--   hello
--   CallStack (from HasCallStack):
--     putStrLnWithCallStack, called at <interactive>:... in interactive:Ghci...
--   
-- -- GHC solves HasCallStack constraints in three steps: -- --
    --
  1. If there is a CallStack in scope -- i.e. the enclosing -- function has a HasCallStack constraint -- GHC will append the -- new call-site to the existing CallStack.
  2. --
  3. If there is no CallStack in scope -- e.g. in the GHCi -- session above -- and the enclosing definition does not have an -- explicit type signature, GHC will infer a HasCallStack -- constraint for the enclosing definition (subject to the monomorphism -- restriction).
  4. --
  5. If there is no CallStack in scope and the enclosing -- definition has an explicit type signature, GHC will solve the -- HasCallStack constraint for the singleton CallStack -- containing just the current call-site.
  6. --
-- -- CallStacks do not interact with the RTS and do not require -- compilation with -prof. On the other hand, as they are built -- up explicitly via the HasCallStack constraints, they will -- generally not contain as much information as the simulated call-stacks -- maintained by the RTS. -- -- A CallStack is a [(String, SrcLoc)]. The -- String is the name of function that was called, the -- SrcLoc is the call-site. The list is ordered with the most -- recently called function at the head. -- -- NOTE: The intrepid user may notice that HasCallStack is just an -- alias for an implicit parameter ?callStack :: CallStack. This -- is an implementation detail and should not be considered part -- of the CallStack API, we may decide to change the -- implementation in the future. data CallStack -- | Extract a list of call-sites from the CallStack. -- -- The list is ordered by most recent call. getCallStack :: CallStack -> [([Char], SrcLoc)] -- | Pretty print a CallStack. prettyCallStack :: CallStack -> String instance GHC.Classes.Eq Effectful.Error.Static.ErrorId instance GHC.Show.Show Effectful.Error.Static.ErrorWrapper instance GHC.Exception.Type.Exception Effectful.Error.Static.ErrorWrapper -- | Provider of the MonadFail instance for Eff. module Effectful.Fail -- | Provide the ability to use the MonadFail instance of -- Eff. data Fail :: Effect [Fail] :: String -> Fail m a -- | Run the Fail effect via Error. runFail :: Eff (Fail : es) a -> Eff es (Either String a) -- | Run the Fail effect via the MonadFail instance for -- IO. runFailIO :: IOE :> es => Eff (Fail : es) a -> Eff es a -- | The dynamically dispatched variant of the Error effect. -- -- Note: unless you plan to change interpretations at runtime, -- it's recommended to use the statically dispatched variant, i.e. -- Effectful.Error.Static. module Effectful.Error.Dynamic -- | Provide the ability to handle errors of type e. data Error e :: Effect [ThrowError] :: e -> Error e m a [CatchError] :: m a -> (CallStack -> e -> m a) -> Error e m a -- | Handle errors of type e (via Effectful.Error.Static). runError :: Eff (Error e : es) a -> Eff es (Either (CallStack, e) a) -- | Handle errors of type e (via Effectful.Error.Static). -- In case of an error discard the CallStack. runErrorNoCallStack :: Eff (Error e : es) a -> Eff es (Either e a) -- | Throw an error of type e. throwError :: (HasCallStack, Error e :> es) => e -> Eff es a -- | Handle an error of type e. catchError :: (HasCallStack, Error e :> es) => Eff es a -> (CallStack -> e -> Eff es a) -> Eff es a -- | The same as flip catchError, which is useful in -- situations where the code for the handler is shorter. handleError :: Error e :> es => (CallStack -> e -> Eff es a) -> Eff es a -> Eff es a -- | Similar to catchError, but returns an Either result -- which is a Right if no error was thrown and a Left -- otherwise. tryError :: (HasCallStack, Error e :> es) => Eff es a -> Eff es (Either (CallStack, e) a) -- | Request a CallStack. -- -- NOTE: The implicit parameter ?callStack :: CallStack is an -- implementation detail and should not be considered part of the -- CallStack API, we may decide to change the implementation in -- the future. type HasCallStack = ?callStack :: CallStack -- | CallStacks are a lightweight method of obtaining a partial -- call-stack at any point in the program. -- -- A function can request its call-site with the HasCallStack -- constraint. For example, we can define -- --
--   putStrLnWithCallStack :: HasCallStack => String -> IO ()
--   
-- -- as a variant of putStrLn that will get its call-site and -- print it, along with the string given as argument. We can access the -- call-stack inside putStrLnWithCallStack with -- callStack. -- --
--   >>> :{
--   putStrLnWithCallStack :: HasCallStack => String -> IO ()
--   putStrLnWithCallStack msg = do
--     putStrLn msg
--     putStrLn (prettyCallStack callStack)
--   :}
--   
-- -- Thus, if we call putStrLnWithCallStack we will get a -- formatted call-stack alongside our string. -- --
--   >>> putStrLnWithCallStack "hello"
--   hello
--   CallStack (from HasCallStack):
--     putStrLnWithCallStack, called at <interactive>:... in interactive:Ghci...
--   
-- -- GHC solves HasCallStack constraints in three steps: -- --
    --
  1. If there is a CallStack in scope -- i.e. the enclosing -- function has a HasCallStack constraint -- GHC will append the -- new call-site to the existing CallStack.
  2. --
  3. If there is no CallStack in scope -- e.g. in the GHCi -- session above -- and the enclosing definition does not have an -- explicit type signature, GHC will infer a HasCallStack -- constraint for the enclosing definition (subject to the monomorphism -- restriction).
  4. --
  5. If there is no CallStack in scope and the enclosing -- definition has an explicit type signature, GHC will solve the -- HasCallStack constraint for the singleton CallStack -- containing just the current call-site.
  6. --
-- -- CallStacks do not interact with the RTS and do not require -- compilation with -prof. On the other hand, as they are built -- up explicitly via the HasCallStack constraints, they will -- generally not contain as much information as the simulated call-stacks -- maintained by the RTS. -- -- A CallStack is a [(String, SrcLoc)]. The -- String is the name of function that was called, the -- SrcLoc is the call-site. The list is ordered with the most -- recently called function at the head. -- -- NOTE: The intrepid user may notice that HasCallStack is just an -- alias for an implicit parameter ?callStack :: CallStack. This -- is an implementation detail and should not be considered part -- of the CallStack API, we may decide to change the -- implementation in the future. data CallStack -- | Extract a list of call-sites from the CallStack. -- -- The list is ordered by most recent call. getCallStack :: CallStack -> [([Char], SrcLoc)] -- | Pretty print a CallStack. prettyCallStack :: CallStack -> String -- | Provider of the Alternative and MonadPlus instance for -- Eff. module Effectful.NonDet -- | Provide the ability to use the Alternative and MonadPlus -- instance of Eff. data NonDet :: Effect [Empty] :: NonDet m a [:<|>:] :: m a -> m a -> NonDet m a -- | Policy of dealing with modifications to thread local state in -- the environment in branches that end up calling the Empty -- operation. -- -- Note: OnEmptyKeep is significantly faster as there is no -- need to back up the environment on each call to :<|>:. data OnEmptyPolicy -- | Keep modifications on Empty. OnEmptyKeep :: OnEmptyPolicy -- | Rollback modifications on Empty. OnEmptyRollback :: OnEmptyPolicy -- | Run the NonDet effect with a given OnEmptyPolicy. -- -- Note: :<|>: executes the second computation if -- (and only if) the first computation calls Empty. runNonDet :: OnEmptyPolicy -> Eff (NonDet : es) a -> Eff es (Either CallStack a) -- | Specialized version of empty with the HasCallStack -- constraint for tracking purposes. emptyEff :: (HasCallStack, NonDet :> es) => Eff es a -- | Specialized version of asum with the HasCallStack -- constraint for tracking purposes. sumEff :: (HasCallStack, Foldable t, NonDet :> es) => t (Eff es a) -> Eff es a -- | A monoid on applicative functors. -- -- If defined, some and many should be the least solutions -- of the equations: -- -- class Applicative f => Alternative (f :: Type -> Type) -- | The identity of <|> empty :: Alternative f => f a -- | An associative binary operation (<|>) :: Alternative f => f a -> f a -> f a -- | One or more. some :: Alternative f => f a -> f [a] -- | Zero or more. many :: Alternative f => f a -> f [a] infixl 3 <|> -- | Request a CallStack. -- -- NOTE: The implicit parameter ?callStack :: CallStack is an -- implementation detail and should not be considered part of the -- CallStack API, we may decide to change the implementation in -- the future. type HasCallStack = ?callStack :: CallStack -- | CallStacks are a lightweight method of obtaining a partial -- call-stack at any point in the program. -- -- A function can request its call-site with the HasCallStack -- constraint. For example, we can define -- --
--   putStrLnWithCallStack :: HasCallStack => String -> IO ()
--   
-- -- as a variant of putStrLn that will get its call-site and -- print it, along with the string given as argument. We can access the -- call-stack inside putStrLnWithCallStack with -- callStack. -- --
--   >>> :{
--   putStrLnWithCallStack :: HasCallStack => String -> IO ()
--   putStrLnWithCallStack msg = do
--     putStrLn msg
--     putStrLn (prettyCallStack callStack)
--   :}
--   
-- -- Thus, if we call putStrLnWithCallStack we will get a -- formatted call-stack alongside our string. -- --
--   >>> putStrLnWithCallStack "hello"
--   hello
--   CallStack (from HasCallStack):
--     putStrLnWithCallStack, called at <interactive>:... in interactive:Ghci...
--   
-- -- GHC solves HasCallStack constraints in three steps: -- --
    --
  1. If there is a CallStack in scope -- i.e. the enclosing -- function has a HasCallStack constraint -- GHC will append the -- new call-site to the existing CallStack.
  2. --
  3. If there is no CallStack in scope -- e.g. in the GHCi -- session above -- and the enclosing definition does not have an -- explicit type signature, GHC will infer a HasCallStack -- constraint for the enclosing definition (subject to the monomorphism -- restriction).
  4. --
  5. If there is no CallStack in scope and the enclosing -- definition has an explicit type signature, GHC will solve the -- HasCallStack constraint for the singleton CallStack -- containing just the current call-site.
  6. --
-- -- CallStacks do not interact with the RTS and do not require -- compilation with -prof. On the other hand, as they are built -- up explicitly via the HasCallStack constraints, they will -- generally not contain as much information as the simulated call-stacks -- maintained by the RTS. -- -- A CallStack is a [(String, SrcLoc)]. The -- String is the name of function that was called, the -- SrcLoc is the call-site. The list is ordered with the most -- recently called function at the head. -- -- NOTE: The intrepid user may notice that HasCallStack is just an -- alias for an implicit parameter ?callStack :: CallStack. This -- is an implementation detail and should not be considered part -- of the CallStack API, we may decide to change the -- implementation in the future. data CallStack -- | Extract a list of call-sites from the CallStack. -- -- The list is ordered by most recent call. getCallStack :: CallStack -> [([Char], SrcLoc)] -- | Pretty print a CallStack. prettyCallStack :: CallStack -> String instance GHC.Show.Show Effectful.NonDet.OnEmptyPolicy instance GHC.Classes.Ord Effectful.NonDet.OnEmptyPolicy instance GHC.Generics.Generic Effectful.NonDet.OnEmptyPolicy instance GHC.Classes.Eq Effectful.NonDet.OnEmptyPolicy -- | Provider of the MonadPrim instance for Eff. module Effectful.Prim -- | Provide the ability to perform primitive state-transformer actions. data Prim :: Effect -- | PrimState token for Eff. Used instead of -- RealWorld to prevent the Prim effect from executing -- arbitrary IO actions via ioToPrim. data PrimStateEff -- | Run an Eff computation with primitive state-transformer -- actions. runPrim :: IOE :> es => Eff (Prim : es) a -> Eff es a -- | Support for access to a read only value of a particular type. module Effectful.Reader.Static -- | Provide access to a strict (WHNF), thread local, read only value of -- type r. data Reader r :: Effect -- | Run a Reader effect with the given initial environment. runReader :: r -> Eff (Reader r : es) a -> Eff es a -- | Execute a computation in a modified environment. withReader :: (r1 -> r2) -> Eff (Reader r2 : es) a -> Eff (Reader r1 : es) a -- | Fetch the value of the environment. ask :: Reader r :> es => Eff es r -- | Retrieve a function of the current environment. -- --
--   asks f ≡ f <$> ask
--   
asks :: Reader r :> es => (r -> a) -> Eff es a -- | Execute a computation in a modified environment. -- --
--   runReader r (local f m) ≡ runReader (f r) m
--   
local :: Reader r :> es => (r -> r) -> Eff es a -> Eff es a -- | The dynamically dispatched variant of the Reader effect. -- -- Note: unless you plan to change interpretations at runtime, -- it's recommended to use the statically dispatched variant, i.e. -- Effectful.Reader.Static. module Effectful.Reader.Dynamic data Reader r :: Effect [Ask] :: Reader r m r [Local] :: (r -> r) -> m a -> Reader r m a -- | Run the Reader effect with the given initial environment (via -- Effectful.Reader.Static). runReader :: r -> Eff (Reader r : es) a -> Eff es a -- | Execute a computation in a modified environment. withReader :: (r1 -> r2) -> Eff (Reader r2 : es) a -> Eff (Reader r1 : es) a -- | Fetch the value of the environment. ask :: (HasCallStack, Reader r :> es) => Eff es r -- | Retrieve a function of the current environment. -- --
--   asks f ≡ f <$> ask
--   
asks :: (HasCallStack, Reader r :> es) => (r -> a) -> Eff es a -- | Execute a computation in a modified environment. -- --
--   runReader r (local f m) ≡ runReader (f r) m
--   
local :: (HasCallStack, Reader r :> es) => (r -> r) -> Eff es a -> Eff es a -- | Support for access to a mutable value of a particular type. -- -- The value is thread local. If you want it to be shared between -- threads, use Effectful.State.Static.Shared. -- -- Note: unlike the StateT monad transformer from the -- transformers library, the State effect doesn't discard -- state updates when an exception is received: -- --
--   >>> import qualified Control.Monad.Trans.State.Strict as S
--   
-- --
--   >>> :{
--     (`S.execStateT` "Hi") . handle (\(_::ErrorCall) -> pure ()) $ do
--       S.modify (++ " there!")
--       error "oops"
--   :}
--   "Hi"
--   
-- --
--   >>> :{
--     runEff . execState "Hi" . handle (\(_::ErrorCall) -> pure ()) $ do
--       modify (++ " there!")
--       error "oops"
--   :}
--   "Hi there!"
--   
module Effectful.State.Static.Local -- | Provide access to a strict (WHNF), thread local, mutable value of type -- s. data State s :: Effect -- | Run the State effect with the given initial state and return -- the final value along with the final state. runState :: s -> Eff (State s : es) a -> Eff es (a, s) -- | Run the State effect with the given initial state and return -- the final value, discarding the final state. evalState :: s -> Eff (State s : es) a -> Eff es a -- | Run the State effect with the given initial state and return -- the final state, discarding the final value. execState :: s -> Eff (State s : es) a -> Eff es s -- | Fetch the current value of the state. get :: State s :> es => Eff es s -- | Get a function of the current state. -- --
--   gets f ≡ f <$> get
--   
gets :: State s :> es => (s -> a) -> Eff es a -- | Set the current state to the given value. put :: State s :> es => s -> Eff es () -- | Apply the function to the current state and return a value. state :: State s :> es => (s -> (a, s)) -> Eff es a -- | Apply the function to the current state. -- --
--   modify f ≡ state (\s -> ((), f s))
--   
modify :: State s :> es => (s -> s) -> Eff es () -- | Apply the monadic function to the current state and return a value. stateM :: State s :> es => (s -> Eff es (a, s)) -> Eff es a -- | Apply the monadic function to the current state. -- --
--   modifyM f ≡ stateM (\s -> ((), ) <$> f s)
--   
modifyM :: State s :> es => (s -> Eff es s) -> Eff es () -- | Support for access to a shared, mutable value of a particular type. -- -- The value is shared between multiple threads. If you want each thead -- to manage its own version of the value, use -- Effectful.State.Static.Local. -- -- Note: unlike the StateT monad transformer from the -- transformers library, the State effect doesn't discard -- state updates when an exception is received: -- --
--   >>> import qualified Control.Monad.Trans.State.Strict as S
--   
-- --
--   >>> :{
--     (`S.execStateT` "Hi") . handle (\(_::ErrorCall) -> pure ()) $ do
--       S.modify (++ " there!")
--       error "oops"
--   :}
--   "Hi"
--   
-- --
--   >>> :{
--     runEff . execState "Hi" . handle (\(_::ErrorCall) -> pure ()) $ do
--       modify (++ " there!")
--       error "oops"
--   :}
--   "Hi there!"
--   
module Effectful.State.Static.Shared -- | Provide access to a strict (WHNF), shared, mutable value of type -- s. data State s :: Effect -- | Run the State effect with the given initial state and return -- the final value along with the final state. runState :: s -> Eff (State s : es) a -> Eff es (a, s) -- | Run the State effect with the given initial state and return -- the final value, discarding the final state. evalState :: s -> Eff (State s : es) a -> Eff es a -- | Run the State effect with the given initial state and return -- the final state, discarding the final value. execState :: s -> Eff (State s : es) a -> Eff es s -- | Run the State effect with the given initial state MVar -- and return the final value along with the final state. runStateMVar :: MVar s -> Eff (State s : es) a -> Eff es (a, s) -- | Run the State effect with the given initial state MVar -- and return the final value, discarding the final state. evalStateMVar :: MVar s -> Eff (State s : es) a -> Eff es a -- | Run the State effect with the given initial state MVar -- and return the final state, discarding the final value. execStateMVar :: MVar s -> Eff (State s : es) a -> Eff es s -- | Fetch the current value of the state. get :: State s :> es => Eff es s -- | Get a function of the current state. -- --
--   gets f ≡ f <$> get
--   
gets :: State s :> es => (s -> a) -> Eff es a -- | Set the current state to the given value. put :: State s :> es => s -> Eff es () -- | Apply the function to the current state and return a value. -- -- Note: this function gets an exclusive access to the state for -- its duration. state :: State s :> es => (s -> (a, s)) -> Eff es a -- | Apply the function to the current state. -- --
--   modify f ≡ state (\s -> ((), f s))
--   
-- -- Note: this function gets an exclusive access to the state for -- its duration. modify :: State s :> es => (s -> s) -> Eff es () -- | Apply the monadic function to the current state and return a value. -- -- Note: this function gets an exclusive access to the state for -- its duration. stateM :: State s :> es => (s -> Eff es (a, s)) -> Eff es a -- | Apply the monadic function to the current state. -- --
--   modifyM f ≡ stateM (\s -> ((), ) <$> f s)
--   
-- -- Note: this function gets an exclusive access to the state for -- its duration. modifyM :: State s :> es => (s -> Eff es s) -> Eff es () -- | The dynamically dispatched variant of the State effect. -- -- Note: unless you plan to change interpretations at runtime, -- it's recommended to use one of the statically dispatched variants, -- i.e. Effectful.State.Static.Local or -- Effectful.State.Static.Shared. module Effectful.State.Dynamic -- | Provide access to a mutable value of type s. data State s :: Effect [Get] :: State s m s [Put] :: s -> State s m () [State] :: (s -> (a, s)) -> State s m a [StateM] :: (s -> m (a, s)) -> State s m a -- | Run the State effect with the given initial state and return -- the final value along with the final state (via -- Effectful.State.Static.Local). runStateLocal :: s -> Eff (State s : es) a -> Eff es (a, s) -- | Run the State effect with the given initial state and return -- the final value, discarding the final state (via -- Effectful.State.Static.Local). evalStateLocal :: s -> Eff (State s : es) a -> Eff es a -- | Run the State effect with the given initial state and return -- the final state, discarding the final value (via -- Effectful.State.Static.Local). execStateLocal :: s -> Eff (State s : es) a -> Eff es s -- | Run the State effect with the given initial state and return -- the final value along with the final state (via -- Effectful.State.Static.Shared). runStateShared :: s -> Eff (State s : es) a -> Eff es (a, s) -- | Run the State effect with the given initial state and return -- the final value, discarding the final state (via -- Effectful.State.Static.Shared). evalStateShared :: s -> Eff (State s : es) a -> Eff es a -- | Run the State effect with the given initial state and return -- the final state, discarding the final value (via -- Effectful.State.Static.Shared). execStateShared :: s -> Eff (State s : es) a -> Eff es s -- | Fetch the current value of the state. get :: (HasCallStack, State s :> es) => Eff es s -- | Get a function of the current state. -- --
--   gets f ≡ f <$> get
--   
gets :: (HasCallStack, State s :> es) => (s -> a) -> Eff es a -- | Set the current state to the given value. put :: (HasCallStack, State s :> es) => s -> Eff es () -- | Apply the function to the current state and return a value. state :: (HasCallStack, State s :> es) => (s -> (a, s)) -> Eff es a -- | Apply the function to the current state. -- --
--   modify f ≡ state (\s -> ((), f s))
--   
modify :: (HasCallStack, State s :> es) => (s -> s) -> Eff es () -- | Apply the monadic function to the current state and return a value. stateM :: (HasCallStack, State s :> es) => (s -> Eff es (a, s)) -> Eff es a -- | Apply the monadic function to the current state. -- --
--   modifyM f ≡ stateM (\s -> ((), ) <$> f s)
--   
modifyM :: (HasCallStack, State s :> es) => (s -> Eff es s) -> Eff es () -- | Support for access to a write only value of a particular type. -- -- The value is thread local. If you want it to be shared between -- threads, use Effectful.Writer.Static.Shared. -- -- Warning: Writer's state will be accumulated via -- left-associated uses of <>, which makes it -- unsuitable for use with types for which such pattern is inefficient. -- This applies, in particular, to the standard list type, which -- makes the Writer effect pretty niche. -- -- Note: while the Writer from the transformers -- package includes additional operations pass and censor, -- they don't cooperate with runtime exceptions very well, so they're -- deliberately omitted here. module Effectful.Writer.Static.Local -- | Provide access to a strict (WHNF), thread local, write only value of -- type w. data Writer w :: Effect -- | Run a Writer effect and return the final value along with the -- final output. runWriter :: Monoid w => Eff (Writer w : es) a -> Eff es (a, w) -- | Run a Writer effect and return the final output, discarding the -- final value. execWriter :: Monoid w => Eff (Writer w : es) a -> Eff es w -- | Append the given output to the overall output of the Writer. tell :: (Writer w :> es, Monoid w) => w -> Eff es () -- | Execute an action and append its output to the overall output of the -- Writer. -- -- Note: if an exception is received while the action is executed, -- the partial output of the action will still be appended to the overall -- output of the Writer: -- --
--   >>> :{
--     runEff . execWriter @String $ do
--       tell "Hi"
--       handle (\(_::ErrorCall) -> pure ((), "")) $ do
--         tell " there"
--         listen $ do
--           tell "!"
--           error "oops"
--   :}
--   "Hi there!"
--   
listen :: (Writer w :> es, Monoid w) => Eff es a -> Eff es (a, w) -- | Execute an action and append its output to the overall output of the -- Writer, then return the final value along with a function of -- the recorded output. -- --
--   listens f m ≡ second f <$> listen m
--   
listens :: (Writer w :> es, Monoid w) => (w -> b) -> Eff es a -> Eff es (a, b) -- | Support for access to a write only value of a particular type. -- -- The value is shared between multiple threads. If you want each thead -- to manage its own version of the value, use -- Effectful.Writer.Static.Local. -- -- Warning: Writer's state will be accumulated via -- left-associated uses of <>, which makes it -- unsuitable for use with types for which such pattern is inefficient. -- This applies, in particular, to the standard list type, which -- makes the Writer effect pretty niche. -- -- Note: while the Writer from the transformers -- package includes additional operations pass and censor, -- they don't cooperate with runtime exceptions very well, so they're -- deliberately omitted here. module Effectful.Writer.Static.Shared -- | Provide access to a strict (WHNF), shared, write only value of type -- w. data Writer w :: Effect -- | Run a Writer effect and return the final value along with the -- final output. runWriter :: Monoid w => Eff (Writer w : es) a -> Eff es (a, w) -- | Run a Writer effect and return the final output, discarding the -- final value. execWriter :: Monoid w => Eff (Writer w : es) a -> Eff es w -- | Append the given output to the overall output of the Writer. tell :: (Writer w :> es, Monoid w) => w -> Eff es () -- | Execute an action and append its output to the overall output of the -- Writer. -- -- Note: if an exception is received while the action is executed, -- the partial output of the action will still be appended to the overall -- output of the Writer: -- --
--   >>> :{
--     runEff . execWriter @String $ do
--       tell "Hi"
--       handle (\(_::ErrorCall) -> pure ((), "")) $ do
--         tell " there"
--         listen $ do
--           tell "!"
--           error "oops"
--   :}
--   "Hi there!"
--   
listen :: (Writer w :> es, Monoid w) => Eff es a -> Eff es (a, w) -- | Execute an action and append its output to the overall output of the -- Writer, then return the final value along with a function of -- the recorded output. -- --
--   listens f m ≡ second f <$> listen m
--   
listens :: (Writer w :> es, Monoid w) => (w -> b) -> Eff es a -> Eff es (a, b) -- | The dynamically dispatched variant of the Writer effect. -- -- Note: unless you plan to change interpretations at runtime, -- it's recommended to use one of the statically dispatched variants, -- i.e. Effectful.Writer.Static.Local or -- Effectful.Writer.Static.Shared. module Effectful.Writer.Dynamic -- | Provide access to a write only value of type w. data Writer w :: Effect [Tell] :: w -> Writer w m () [Listen] :: m a -> Writer w m (a, w) -- | Run the Writer effect and return the final value along with the -- final output (via Effectful.Writer.Static.Local). runWriterLocal :: Monoid w => Eff (Writer w : es) a -> Eff es (a, w) -- | Run a Writer effect and return the final output, discarding the -- final value (via Effectful.Writer.Static.Local). execWriterLocal :: Monoid w => Eff (Writer w : es) a -> Eff es w -- | Run the Writer effect and return the final value along with the -- final output (via Effectful.Writer.Static.Shared). runWriterShared :: Monoid w => Eff (Writer w : es) a -> Eff es (a, w) -- | Run the Writer effect and return the final output, discarding -- the final value (via Effectful.Writer.Static.Shared). execWriterShared :: Monoid w => Eff (Writer w : es) a -> Eff es w -- | Append the given output to the overall output of the Writer. tell :: (HasCallStack, Writer w :> es) => w -> Eff es () -- | Execute an action and append its output to the overall output of the -- Writer. listen :: (HasCallStack, Writer w :> es) => Eff es a -> Eff es (a, w) -- | Execute an action and append its output to the overall output of the -- Writer, then return the final value along with a function of -- the recorded output. -- --
--   listens f m ≡ second f <$> listen m
--   
listens :: (HasCallStack, Writer w :> es) => (w -> b) -> Eff es a -> Eff es (a, b)