-- 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.5.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. See -- https://github.com/haskell-effectful/effectful/issues/52#issuecomment-1269155485 -- for more information. type family xs :>> es :: Constraint -- | Provide evidence that subEs is a subset of es. class KnownPrefix es => Subset (subEs :: [Effect]) (es :: [Effect]) subsetFullyKnown :: Subset subEs es => Bool reifyIndices :: Subset subEs es => [Int] -- | Provide evidence that subEs is a known subset of es. class Subset subEs es => KnownSubset (subEs :: [Effect]) (es :: [Effect]) -- | Calculate length of a statically known prefix of es. class KnownPrefix (es :: [Effect]) prefixLength :: KnownPrefix es => Int -- | Require that subEs is the unknown suffix of es. class (subEs :: [Effect]) `IsUnknownSuffixOf` (es :: [Effect]) -- | Append two type-level lists together. type family (xs :: [Effect]) ++ (ys :: [Effect]) :: [Effect] infixr 5 ++ -- | Calculate length of a list of known effects. class KnownEffects (es :: [Effect]) knownEffectsLength :: KnownEffects es => Int -- | The kind of types with lifted values. For example Int :: -- Type. type Type = TYPE LiftedRep instance Effectful.Internal.Effect.KnownEffects es => Effectful.Internal.Effect.KnownEffects (e : es) instance Effectful.Internal.Effect.KnownEffects '[] instance (Effectful.Internal.Effect.KnownPrefix es, Effectful.Internal.Effect.IsUnknownSuffixOf subEs es) => Effectful.Internal.Effect.Subset subEs es instance (subEs GHC.Types.~ es) => Effectful.Internal.Effect.IsUnknownSuffixOf subEs es instance Effectful.Internal.Effect.IsUnknownSuffixOf subEs es => Effectful.Internal.Effect.IsUnknownSuffixOf subEs (e : es) instance Effectful.Internal.Effect.KnownSubset '[] es instance (e Effectful.Internal.Effect.:> es, Effectful.Internal.Effect.KnownSubset subEs es) => Effectful.Internal.Effect.KnownSubset (e : subEs) es instance Effectful.Internal.Effect.KnownPrefix es => Effectful.Internal.Effect.Subset '[] es instance (e Effectful.Internal.Effect.:> es, Effectful.Internal.Effect.Subset subEs es) => Effectful.Internal.Effect.Subset (e : subEs) es instance Effectful.Internal.Effect.KnownPrefix es => Effectful.Internal.Effect.KnownPrefix (e : es) instance Effectful.Internal.Effect.KnownPrefix 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.Utils -- | Version of bracket with an INLINE pragma to work around -- https://gitlab.haskell.org/ghc/ghc/-/issues/22824. inlineBracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c -- | Get an id of a thread that doesn't prevent its garbage collection. weakThreadId :: ThreadId -> Int eqThreadId :: ThreadId -> ThreadId -> Bool -- | 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 toAny :: a -> Any fromAny :: Any -> a -- | A unique with no possibility for CAS contention. -- -- Credits for this go to Edward Kmett. data Unique newUnique :: IO Unique thawCallStack :: CallStack -> CallStack instance GHC.Classes.Eq Effectful.Internal.Utils.Unique 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 Ref -> !IORef' Storage -> Env (es :: [Effect]) [envOffset] :: Env (es :: [Effect]) -> !Int [envRefs] :: Env (es :: [Effect]) -> !PrimArray Ref [envStorage] :: Env (es :: [Effect]) -> !IORef' Storage -- | Reference to the effect in Storage. data Ref Ref :: !Int -> !Version -> Ref -- | Version of the effect. data Version -- | A storage of effects. data Storage Storage :: !Version -> {-# UNPACK #-} !StorageData -> Storage [stVersion] :: Storage -> !Version [stData] :: Storage -> {-# UNPACK #-} !StorageData data StorageData StorageData :: !Int -> !MutablePrimArray RealWorld Version -> !SmallMutableArray RealWorld AnyEffect -> !SmallMutableArray RealWorld AnyRelinker -> StorageData [sdSize] :: StorageData -> !Int [sdVersions] :: StorageData -> !MutablePrimArray RealWorld Version [sdEffects] :: StorageData -> !SmallMutableArray RealWorld AnyEffect [sdRelinkers] :: StorageData -> !SmallMutableArray RealWorld AnyRelinker -- | Make a shallow copy of the StorageData. copyStorageData :: HasCallStack => StorageData -> IO StorageData -- | Restore a shallow copy of the StorageData. -- -- The copy needs to be from the same Env as the target. restoreStorageData :: HasCallStack => StorageData -> Env es -> IO () -- | Relinker in Storage. data AnyRelinker toAnyRelinker :: Relinker (EffectRep (DispatchOf e)) e -> AnyRelinker fromAnyRelinker :: AnyRelinker -> Relinker (EffectRep (DispatchOf e)) e -- | Effect in Storage. data AnyEffect toAnyEffect :: EffectRep (DispatchOf e) e -> AnyEffect fromAnyEffect :: AnyEffect -> EffectRep (DispatchOf e) e -- | 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] :: (HasCallStack => (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 :: HasCallStack => IO (Env '[]) -- | Clone the environment to use it in a different thread. cloneEnv :: HasCallStack => Env es -> IO (Env es) -- | 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 :: HasCallStack => 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 :: HasCallStack => 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. (HasCallStack, 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. (HasCallStack, 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 subEs es. Subset subEs es => Env es -> IO (Env subEs) -- | Extract a specific data type from the environment. getEnv :: forall e es. (HasCallStack, 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. (HasCallStack, 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. (HasCallStack, e :> es) => Env es -> (EffectRep (DispatchOf e) e -> (a, EffectRep (DispatchOf e) e)) -> IO a -- | Modify the data type in the environment (in place). modifyEnv :: forall e es. (HasCallStack, e :> es) => Env es -> (EffectRep (DispatchOf e) e -> EffectRep (DispatchOf e) e) -> IO () instance GHC.Show.Show Effectful.Internal.Env.Version instance Data.Primitive.Types.Prim Effectful.Internal.Env.Version instance GHC.Classes.Ord Effectful.Internal.Env.Version instance GHC.Classes.Eq Effectful.Internal.Env.Version instance Data.Primitive.Types.Prim Effectful.Internal.Env.Ref -- | 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 or the localUnlift family. data UnliftStrategy -- | The sequential strategy is the fastest and a default setting for -- IOE. Any attempt of calling the unlifting function in threads -- distinct from its creator will result in a runtime error. SeqUnlift :: UnliftStrategy -- | Like SeqUnlift, but all unlifted actions will be executed in a -- cloned environment. -- -- The main consequence is that thread local state is forked at the point -- of creation of the unlifting function and its modifications in -- unlifted actions will not affect the main thread of execution (and -- vice versa): -- --
--   >>> import Effectful
--   
--   >>> import Effectful.State.Dynamic
--   
--   >>> :{
--    action :: (IOE :> es, State Int :> es) => Eff es ()
--    action = do
--      modify @Int (+1)
--      withEffToIO SeqForkUnlift $ \unlift -> unlift $ modify @Int (+2)
--      modify @Int (+4)
--   :}
--   
-- --
--   >>> runEff . execStateLocal @Int 0 $ action
--   5
--   
-- --
--   >>> runEff . execStateShared @Int 0 $ action
--   7
--   
-- -- Because of this it's possible to safely use the unlifting function -- outside of the scope of effects it captures, e.g. by creating an -- IO action that executes effectful operations and running it -- later: -- --
--   >>> :{
--     delayed :: UnliftStrategy -> IO (IO String)
--     delayed strategy = runEff . evalStateLocal "Hey" $ do
--       r <- withEffToIO strategy $ \unlift -> pure $ unlift get
--       modify (++ "!!!")
--       pure r
--   :}
--   
-- -- This doesn't work with the SeqUnlift strategy because when the -- returned action runs, State is no longer in scope: -- --
--   >>> join $ delayed SeqUnlift
--   *** Exception: version (...) /= storageVersion (0)
--   ...
--   
-- -- However, it does with the SeqForkUnlift strategy: -- --
--   >>> join $ delayed SeqForkUnlift
--   "Hey"
--   
SeqForkUnlift :: UnliftStrategy -- | The concurrent strategy 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 -- | Concurrent unlift that doesn't preserve the environment between calls -- to the unlifting function in threads other than its creator. ephemeralConcUnlift :: (HasCallStack, forall r. Coercible (m r) (Env es -> IO r)) => Env es -> Int -> ((forall r. m r -> IO r) -> IO a) -> IO a -- | Concurrent unlift that preserves the environment between calls to the -- unlifting function within a particular thread. persistentConcUnlift :: (HasCallStack, forall r. Coercible (m r) (Env es -> IO r)) => Env es -> Bool -> Int -> ((forall r. m r -> IO r) -> IO a) -> 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 :: HasCallStack => 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 for Eff. data NonDet :: Effect [Empty] :: NonDet m a [:<|>:] :: m a -> m a -> NonDet m a -- | Provide the ability to use the MonadFail instance for -- 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 :: HasCallStack => 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 :: (HasCallStack, 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 subEs within es as -- long as subEs is a permutation (with possible duplicates) of -- a subset of es. -- -- Generalizes raise and subsume. -- --
--   >>> data E1 :: Effect
--   
--   >>> data E2 :: Effect
--   
--   >>> data E3 :: Effect
--   
-- -- It makes it possible to rearrange the effect stack however you like: -- --
--   >>> :{
--     shuffle :: Eff (E3 : E1 : E2 : es) a -> Eff (E1 : E2 : E3 : es) a
--     shuffle = inject
--   :}
--   
-- -- It can also turn a monomorphic effect stack into a polymorphic one: -- --
--   >>> :{
--     toPoly :: (E1 :> es, E2 :> es, E3 :> es) => Eff [E1, E2, E3] a -> Eff es a
--     toPoly = inject
--   :}
--   
-- -- Moreover, it allows for hiding specific effects from downstream: -- --
--   >>> :{
--     onlyE1 :: Eff (E1 : es) a -> Eff (E1 : E2 : E3 : es) a
--     onlyE1 = inject
--   :}
--   
-- --
--   >>> :{
--     onlyE2 :: Eff (E2 : es) a -> Eff (E1 : E2 : E3 : es) a
--     onlyE2 = inject
--   :}
--   
-- --
--   >>> :{
--     onlyE3 :: Eff (E3 : es) a -> Eff (E1 : E2 : E3 : es) a
--     onlyE3 = inject
--   :}
--   
-- -- However, it's not possible to inject a computation into an -- incompatible effect stack: -- --
--   >>> :{
--     coerceEs :: Eff es1 a -> Eff es2 a
--     coerceEs = inject
--   :}
--   ...
--   ...Couldn't match type ‘es1’ with ‘es2’
--   ...
--   
inject :: Subset subEs es => Eff subEs a -> Eff es a -- | Provide evidence that subEs is a subset of es. class KnownPrefix es => Subset (subEs :: [Effect]) (es :: [Effect]) -- | The strategy to use when unlifting Eff computations via -- withEffToIO or the localUnlift family. data UnliftStrategy -- | The sequential strategy is the fastest and a default setting for -- IOE. Any attempt of calling the unlifting function in threads -- distinct from its creator will result in a runtime error. SeqUnlift :: UnliftStrategy -- | Like SeqUnlift, but all unlifted actions will be executed in a -- cloned environment. -- -- The main consequence is that thread local state is forked at the point -- of creation of the unlifting function and its modifications in -- unlifted actions will not affect the main thread of execution (and -- vice versa): -- --
--   >>> import Effectful
--   
--   >>> import Effectful.State.Dynamic
--   
--   >>> :{
--    action :: (IOE :> es, State Int :> es) => Eff es ()
--    action = do
--      modify @Int (+1)
--      withEffToIO SeqForkUnlift $ \unlift -> unlift $ modify @Int (+2)
--      modify @Int (+4)
--   :}
--   
-- --
--   >>> runEff . execStateLocal @Int 0 $ action
--   5
--   
-- --
--   >>> runEff . execStateShared @Int 0 $ action
--   7
--   
-- -- Because of this it's possible to safely use the unlifting function -- outside of the scope of effects it captures, e.g. by creating an -- IO action that executes effectful operations and running it -- later: -- --
--   >>> :{
--     delayed :: UnliftStrategy -> IO (IO String)
--     delayed strategy = runEff . evalStateLocal "Hey" $ do
--       r <- withEffToIO strategy $ \unlift -> pure $ unlift get
--       modify (++ "!!!")
--       pure r
--   :}
--   
-- -- This doesn't work with the SeqUnlift strategy because when the -- returned action runs, State is no longer in scope: -- --
--   >>> join $ delayed SeqUnlift
--   *** Exception: version (...) /= storageVersion (0)
--   ...
--   
-- -- However, it does with the SeqForkUnlift strategy: -- --
--   >>> join $ delayed SeqForkUnlift
--   "Hey"
--   
SeqForkUnlift :: UnliftStrategy -- | The concurrent strategy 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. -- -- Note: this strategy is implicitly used by the -- MonadUnliftIO and MonadBaseControl instance for -- Eff. unliftStrategy :: IOE :> es => Eff es UnliftStrategy -- | Locally override the current UnliftStrategy with the given -- value. withUnliftStrategy :: IOE :> es => UnliftStrategy -> Eff es a -> Eff es a -- | Create an unlifting function with the SeqUnlift strategy. For -- the general version see withEffToIO. -- -- Note: usage of this function is preferrable to -- withRunInIO because of explicit unlifting strategy and better -- error reporting. withSeqEffToIO :: (HasCallStack, IOE :> es) => ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a -- | Create an unlifting function with the given strategy. -- -- Note: usage of this function is preferrable to -- withRunInIO because of explicit unlifting strategy and better -- error reporting. withEffToIO :: (HasCallStack, IOE :> es) => UnliftStrategy -> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a -- | Create an unlifting function with the ConcUnlift strategy. -- | Deprecated: Use withEffToIO with the appropriate strategy. withConcEffToIO :: (HasCallStack, IOE :> es) => Persistence -> Limit -> ((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 SeqForkUnlift strategy. seqForkUnliftIO :: 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 :: Effect) (es :: [Effect]) = forall a localEs. (HasCallStack, e :> localEs) => -- | Capture of the local environment for handling local 'Eff' computations -- when @e@ is a higher order effect. LocalEnv localEs es -> -- | The operation. e (Eff localEs) a -> 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 handlerEs -> !EffectHandler e handlerEs -> Handler e relinkHandler :: Relinker Handler e -- | Run a dynamically dispatched effect with the given handler. runHandler :: (HasCallStack, 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 :: (HasCallStack, 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 :: (HasCallStack, 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 :: (HasCallStack, 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 :: (HasCallStack, DispatchOf e ~ Static sideEffects, e :> es) => Eff es (StaticRep e) -- | Set the current representation of the effect to the given value. putStaticRep :: (HasCallStack, 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 :: (HasCallStack, 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 :: (HasCallStack, 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 :: (HasCallStack, DispatchOf e ~ Static sideEffects, e :> es) => (StaticRep e -> StaticRep e) -> Eff es a -> Eff es a 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 really unsafe because: -- -- -- -- Warning: if you disregard the second point, you will experience -- weird bugs, data races or internal consistency check failures. -- -- When in doubt, use unsafeLiftMapIO, especially since this -- version saves only a simple safety check per call of -- reallyUnsafeLiftMapIO f. reallyUnsafeLiftMapIO :: (IO a -> IO b) -> Eff es a -> Eff es b -- | Create an unlifting function. -- -- This function is really unsafe because: -- -- -- -- Warning: if you disregard the second point, you will experience -- weird bugs, data races or internal consistency check failures. -- -- When in doubt, use unsafeSeqUnliftIO, especially since this -- version saves only a simple safety check per call of the unlifting -- function. reallyUnsafeUnliftIO :: ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a -- | 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 data races -- or internal consistency check failures, 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] :: (HasCallStack => (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 :: HasCallStack => 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 :: HasCallStack => Env (e : es) -> IO () -- | Extract a specific data type from the environment. getEnv :: forall e es. (HasCallStack, 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. (HasCallStack, 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. (HasCallStack, e :> es) => Env es -> (EffectRep (DispatchOf e) e -> (a, EffectRep (DispatchOf e) e)) -> IO a -- | Modify the data type in the environment (in place). modifyEnv :: forall e es. (HasCallStack, e :> es) => Env es -> (EffectRep (DispatchOf e) e -> EffectRep (DispatchOf e) e) -> IO () -- | Create an empty environment. emptyEnv :: HasCallStack => IO (Env '[]) -- | Clone the environment to use it in a different thread. cloneEnv :: HasCallStack => Env es -> IO (Env es) -- | 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) -- | 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 :: (HasCallStack, 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 :: (HasCallStack, 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 :: (HasCallStack, 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 :: (HasCallStack, DispatchOf e ~ Static sideEffects, e :> es) => Eff es (StaticRep e) -- | Set the current representation of the effect to the given value. putStaticRep :: (HasCallStack, 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 :: (HasCallStack, 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 :: (HasCallStack, 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 :: (HasCallStack, 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 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. 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 :: HasCallStack => Eff '[] a -> a -- | Run an Eff computation with side effects. -- -- For running pure computations see runPureEff. runEff :: HasCallStack => 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 or the localUnlift family. data UnliftStrategy -- | The sequential strategy is the fastest and a default setting for -- IOE. Any attempt of calling the unlifting function in threads -- distinct from its creator will result in a runtime error. SeqUnlift :: UnliftStrategy -- | Like SeqUnlift, but all unlifted actions will be executed in a -- cloned environment. -- -- The main consequence is that thread local state is forked at the point -- of creation of the unlifting function and its modifications in -- unlifted actions will not affect the main thread of execution (and -- vice versa): -- --
--   >>> import Effectful
--   
--   >>> import Effectful.State.Dynamic
--   
--   >>> :{
--    action :: (IOE :> es, State Int :> es) => Eff es ()
--    action = do
--      modify @Int (+1)
--      withEffToIO SeqForkUnlift $ \unlift -> unlift $ modify @Int (+2)
--      modify @Int (+4)
--   :}
--   
-- --
--   >>> runEff . execStateLocal @Int 0 $ action
--   5
--   
-- --
--   >>> runEff . execStateShared @Int 0 $ action
--   7
--   
-- -- Because of this it's possible to safely use the unlifting function -- outside of the scope of effects it captures, e.g. by creating an -- IO action that executes effectful operations and running it -- later: -- --
--   >>> :{
--     delayed :: UnliftStrategy -> IO (IO String)
--     delayed strategy = runEff . evalStateLocal "Hey" $ do
--       r <- withEffToIO strategy $ \unlift -> pure $ unlift get
--       modify (++ "!!!")
--       pure r
--   :}
--   
-- -- This doesn't work with the SeqUnlift strategy because when the -- returned action runs, State is no longer in scope: -- --
--   >>> join $ delayed SeqUnlift
--   *** Exception: version (...) /= storageVersion (0)
--   ...
--   
-- -- However, it does with the SeqForkUnlift strategy: -- --
--   >>> join $ delayed SeqForkUnlift
--   "Hey"
--   
SeqForkUnlift :: UnliftStrategy -- | The concurrent strategy 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. -- -- Note: this strategy is implicitly used by the -- MonadUnliftIO and MonadBaseControl instance for -- Eff. unliftStrategy :: IOE :> es => Eff es UnliftStrategy -- | Locally override the current UnliftStrategy with the given -- value. withUnliftStrategy :: IOE :> es => UnliftStrategy -> Eff es a -> Eff es a -- | Create an unlifting function with the SeqUnlift strategy. For -- the general version see withEffToIO. -- -- Note: usage of this function is preferrable to -- withRunInIO because of explicit unlifting strategy and better -- error reporting. withSeqEffToIO :: (HasCallStack, IOE :> es) => ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a -- | Create an unlifting function with the given strategy. -- -- Note: usage of this function is preferrable to -- withRunInIO because of explicit unlifting strategy and better -- error reporting. withEffToIO :: (HasCallStack, IOE :> es) => UnliftStrategy -> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a -- | Create an unlifting function with the ConcUnlift strategy. -- | Deprecated: Use withEffToIO with the appropriate strategy. withConcEffToIO :: (HasCallStack, IOE :> es) => Persistence -> Limit -> ((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 subEs within es as -- long as subEs is a permutation (with possible duplicates) of -- a subset of es. -- -- Generalizes raise and subsume. -- --
--   >>> data E1 :: Effect
--   
--   >>> data E2 :: Effect
--   
--   >>> data E3 :: Effect
--   
-- -- It makes it possible to rearrange the effect stack however you like: -- --
--   >>> :{
--     shuffle :: Eff (E3 : E1 : E2 : es) a -> Eff (E1 : E2 : E3 : es) a
--     shuffle = inject
--   :}
--   
-- -- It can also turn a monomorphic effect stack into a polymorphic one: -- --
--   >>> :{
--     toPoly :: (E1 :> es, E2 :> es, E3 :> es) => Eff [E1, E2, E3] a -> Eff es a
--     toPoly = inject
--   :}
--   
-- -- Moreover, it allows for hiding specific effects from downstream: -- --
--   >>> :{
--     onlyE1 :: Eff (E1 : es) a -> Eff (E1 : E2 : E3 : es) a
--     onlyE1 = inject
--   :}
--   
-- --
--   >>> :{
--     onlyE2 :: Eff (E2 : es) a -> Eff (E1 : E2 : E3 : es) a
--     onlyE2 = inject
--   :}
--   
-- --
--   >>> :{
--     onlyE3 :: Eff (E3 : es) a -> Eff (E1 : E2 : E3 : es) a
--     onlyE3 = inject
--   :}
--   
-- -- However, it's not possible to inject a computation into an -- incompatible effect stack: -- --
--   >>> :{
--     coerceEs :: Eff es1 a -> Eff es2 a
--     coerceEs = inject
--   :}
--   ...
--   ...Couldn't match type ‘es1’ with ‘es2’
--   ...
--   
inject :: Subset subEs es => Eff subEs a -> Eff es a -- | Provide evidence that subEs is a subset of es. class KnownPrefix es => Subset (subEs :: [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 function run provided by withRunInIO, it -- must meet the monad transformer laws as reformulated for -- MonadUnliftIO: -- -- -- -- Instances of MonadUnliftIO must also satisfy the following -- laws: -- -- -- -- As an example of an invalid instance, a naive implementation of -- MonadUnliftIO (StateT s m) might be -- --
--   withRunInIO inner =
--     StateT $ \s ->
--       withRunInIO $ \run ->
--         inner (run . flip evalStateT s)
--   
-- -- This breaks the identity law because the inner run m would -- throw away any state changes in m. 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 runtime exceptions. -- -- This module supplies thin wrappers over functions from -- Control.Exception as well as several utility functions for -- convenience. -- -- Note: the Eff monad provides instances for -- MonadThrow, MonadCatch and MonadMask, so any -- existing code that uses them remains compatible. module Effectful.Exception -- | Lifted throwIO. throwIO :: (HasCallStack, Exception e) => e -> Eff es a -- | Lifted catch. catch :: Exception e => Eff es a -> (e -> Eff es a) -> Eff es a -- | A variant of catch that fully forces evaluation of the result -- value to find all impure exceptions. catchDeep :: (Exception e, NFData a) => Eff es a -> (e -> Eff es a) -> Eff es a -- | Lifted catchJust. catchJust :: Exception e => (e -> Maybe b) -> Eff es a -> (b -> Eff es a) -> Eff es a -- | Catch an exception only if it satisfies a specific predicate. catchIf :: Exception e => (e -> Bool) -> Eff es a -> (e -> Eff es a) -> Eff es a -- | catch specialized to catch IOException. catchIO :: Eff es a -> (IOException -> Eff es a) -> Eff es a -- | catch specialized to catch all exceptions considered to be -- synchronous. -- --
--   catchSynccatchIf @SomeException isSyncException
--   
-- -- See the check exception type section for more information. catchSync :: Eff es a -> (SomeException -> Eff es a) -> Eff es a -- | A variant of catchSync that fully forces evaluation of the -- result value to find all impure exceptions. catchSyncDeep :: NFData a => Eff es a -> (SomeException -> Eff es a) -> Eff es a -- | Flipped version of catch. handle :: Exception e => (e -> Eff es a) -> Eff es a -> Eff es a -- | Flipped version of catchDeep. handleDeep :: (Exception e, NFData a) => (e -> Eff es a) -> Eff es a -> Eff es a -- | Flipped version of catchJust. handleJust :: (HasCallStack, Exception e) => (e -> Maybe b) -> (b -> Eff es a) -> Eff es a -> Eff es a -- | Flipped version of catchIf. handleIf :: Exception e => (e -> Bool) -> (e -> Eff es a) -> Eff es a -> Eff es a -- | Flipped version of catchIO. handleIO :: (IOException -> Eff es a) -> Eff es a -> Eff es a -- | Flipped version of catchSync. handleSync :: (SomeException -> Eff es a) -> Eff es a -> Eff es a -- | Flipped version of catchSyncDeep. handleSyncDeep :: NFData a => (SomeException -> Eff es a) -> Eff es a -> Eff es a -- | Lifted try. try :: Exception e => Eff es a -> Eff es (Either e a) -- | A variant of try that fully forces evaluation of the result -- value to find all impure exceptions. tryDeep :: (Exception e, NFData a) => Eff es a -> Eff es (Either e a) -- | Lifted tryJust. tryJust :: Exception e => (e -> Maybe b) -> Eff es a -> Eff es (Either b a) -- | Catch an exception only if it satisfies a specific predicate. tryIf :: Exception e => (e -> Bool) -> Eff es a -> Eff es (Either e a) -- | try specialized to catch IOException. tryIO :: Eff es a -> Eff es (Either IOException a) -- | try specialized to catch all exceptions considered to be -- synchronous. -- --
--   trySynctryIf @SomeException isSyncException
--   
-- -- See the check exception type section for more information. trySync :: Eff es a -> Eff es (Either SomeException a) -- | A variant of trySync that fully forces evaluation of the result -- value to find all impure exceptions. trySyncDeep :: NFData a => Eff es a -> Eff es (Either SomeException a) -- | Generalized version of Handler data () => Handler (m :: Type -> Type) a Handler :: (e -> m a) -> Handler (m :: Type -> Type) a -- | Lifted catches. catches :: Eff es a -> [Handler (Eff es) a] -> Eff es a -- | A variant of catches that fully forces evaluation of the result -- value to find all impure exceptions. catchesDeep :: NFData a => Eff es a -> [Handler (Eff es) a] -> Eff es a -- | Lifted bracket. bracket :: Eff es a -> (a -> Eff es b) -> (a -> Eff es c) -> Eff es c -- | Lifted bracket_. bracket_ :: Eff es a -> Eff es b -> Eff es c -> Eff es c -- | Lifted bracketOnError. bracketOnError :: Eff es a -> (a -> Eff es b) -> (a -> Eff es c) -> Eff es c -- | Generalization of bracket. -- -- See generalBracket for more information. generalBracket :: Eff es a -> (a -> ExitCase c -> Eff es b) -> (a -> Eff es c) -> Eff es (c, b) -- | A MonadMask computation may either succeed with a value, abort -- with an exception, or abort for some other reason. For example, in -- ExceptT e IO you can use throwM to abort with an -- exception (ExitCaseException) or throwE to abort with a -- value of type e (ExitCaseAbort). data () => ExitCase a ExitCaseSuccess :: a -> ExitCase a ExitCaseException :: SomeException -> ExitCase a ExitCaseAbort :: ExitCase a -- | Lifted finally. finally :: Eff es a -> Eff es b -> Eff es a -- | Lifted onException. onException :: Eff es a -> Eff es b -> Eff es a -- | Lifted evaluate. evaluate :: a -> Eff es a -- | Deeply evaluate a value using evaluate and NFData. evaluateDeep :: NFData a => a -> Eff es a -- | Check if the given exception is considered synchronous. isSyncException :: Exception e => e -> Bool -- | Check if the given exception is considered asynchronous. isAsyncException :: Exception e => e -> Bool -- | Lifted mask. mask :: ((forall r. Eff es r -> Eff es r) -> Eff es a) -> Eff es a -- | Lifted mask_. mask_ :: Eff es a -> Eff es a -- | Lifted uninterruptibleMask. uninterruptibleMask :: ((forall r. Eff es r -> Eff es r) -> Eff es a) -> Eff es a -- | Lifted uninterruptibleMask_. uninterruptibleMask_ :: Eff es a -> Eff es a -- | Describes the behaviour of a thread when an asynchronous exception is -- received. data () => MaskingState -- | asynchronous exceptions are unmasked (the normal state) Unmasked :: MaskingState -- | the state during mask: asynchronous exceptions are masked, but -- blocking operations may still be interrupted MaskedInterruptible :: MaskingState -- | the state during uninterruptibleMask: asynchronous exceptions -- are masked, and blocking operations may not be interrupted MaskedUninterruptible :: MaskingState -- | Lifted getMaskingState. getMaskingState :: Eff es MaskingState -- | Lifted interruptible. interruptible :: Eff es a -> Eff es a -- | Lifted allowInterrupt. allowInterrupt :: Eff es () -- | The SomeException type is the root of the exception type -- hierarchy. When an exception of type e is thrown, behind the -- scenes it is encapsulated in a SomeException. data () => SomeException SomeException :: e -> SomeException -- | Any type that you wish to throw or catch as an exception must be an -- instance of the Exception class. The simplest case is a new -- exception type directly below the root: -- --
--   data MyException = ThisException | ThatException
--       deriving Show
--   
--   instance Exception MyException
--   
-- -- The default method definitions in the Exception class do what -- we need in this case. You can now throw and catch -- ThisException and ThatException as exceptions: -- --
--   *Main> throw ThisException `catch` \e -> putStrLn ("Caught " ++ show (e :: MyException))
--   Caught ThisException
--   
-- -- In more complicated examples, you may wish to define a whole hierarchy -- of exceptions: -- --
--   ---------------------------------------------------------------------
--   -- Make the root exception type for all the exceptions in a compiler
--   
--   data SomeCompilerException = forall e . Exception e => SomeCompilerException e
--   
--   instance Show SomeCompilerException where
--       show (SomeCompilerException e) = show e
--   
--   instance Exception SomeCompilerException
--   
--   compilerExceptionToException :: Exception e => e -> SomeException
--   compilerExceptionToException = toException . SomeCompilerException
--   
--   compilerExceptionFromException :: Exception e => SomeException -> Maybe e
--   compilerExceptionFromException x = do
--       SomeCompilerException a <- fromException x
--       cast a
--   
--   ---------------------------------------------------------------------
--   -- Make a subhierarchy for exceptions in the frontend of the compiler
--   
--   data SomeFrontendException = forall e . Exception e => SomeFrontendException e
--   
--   instance Show SomeFrontendException where
--       show (SomeFrontendException e) = show e
--   
--   instance Exception SomeFrontendException where
--       toException = compilerExceptionToException
--       fromException = compilerExceptionFromException
--   
--   frontendExceptionToException :: Exception e => e -> SomeException
--   frontendExceptionToException = toException . SomeFrontendException
--   
--   frontendExceptionFromException :: Exception e => SomeException -> Maybe e
--   frontendExceptionFromException x = do
--       SomeFrontendException a <- fromException x
--       cast a
--   
--   ---------------------------------------------------------------------
--   -- Make an exception type for a particular frontend compiler exception
--   
--   data MismatchedParentheses = MismatchedParentheses
--       deriving Show
--   
--   instance Exception MismatchedParentheses where
--       toException   = frontendExceptionToException
--       fromException = frontendExceptionFromException
--   
-- -- We can now catch a MismatchedParentheses exception as -- MismatchedParentheses, SomeFrontendException or -- SomeCompilerException, but not other types, e.g. -- IOException: -- --
--   *Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: MismatchedParentheses))
--   Caught MismatchedParentheses
--   *Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeFrontendException))
--   Caught MismatchedParentheses
--   *Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeCompilerException))
--   Caught MismatchedParentheses
--   *Main> throw MismatchedParentheses `catch` \e -> putStrLn ("Caught " ++ show (e :: IOException))
--   *** Exception: MismatchedParentheses
--   
class (Typeable e, Show e) => Exception e toException :: Exception e => e -> SomeException fromException :: Exception e => SomeException -> Maybe e -- | Render this exception value in a human-friendly manner. -- -- Default implementation: show. displayException :: Exception e => e -> String -- | This function maps one exception into another as proposed in the paper -- "A semantics for imprecise exceptions". mapException :: (Exception e1, Exception e2) => (e1 -> e2) -> a -> a -- | Exceptions that occur in the IO monad. An -- IOException records a more specific error type, a descriptive -- string and maybe the handle that was used when the error was flagged. data () => IOException -- | Arithmetic exceptions. data () => ArithException Overflow :: ArithException Underflow :: ArithException LossOfPrecision :: ArithException DivideByZero :: ArithException Denormal :: ArithException RatioZeroDenominator :: ArithException -- | Exceptions generated by array operations data () => ArrayException -- | An attempt was made to index an array outside its declared bounds. IndexOutOfBounds :: String -> ArrayException -- | An attempt was made to evaluate an element of an array that had not -- been initialized. UndefinedElement :: String -> ArrayException -- | assert was applied to False. newtype () => AssertionFailed AssertionFailed :: String -> AssertionFailed -- | A class method without a definition (neither a default definition, nor -- a definition in the appropriate instance) was called. The -- String gives information about which method it was. newtype () => NoMethodError NoMethodError :: String -> NoMethodError -- | A pattern match failed. The String gives information about -- the source location of the pattern. newtype () => PatternMatchFail PatternMatchFail :: String -> PatternMatchFail -- | An uninitialised record field was used. The String gives -- information about the source location where the record was -- constructed. newtype () => RecConError RecConError :: String -> RecConError -- | A record selector was applied to a constructor without the appropriate -- field. This can only happen with a datatype with multiple -- constructors, where some fields are in one constructor but not -- another. The String gives information about the source -- location of the record selector. newtype () => RecSelError RecSelError :: String -> RecSelError -- | A record update was performed on a constructor without the appropriate -- field. This can only happen with a datatype with multiple -- constructors, where some fields are in one constructor but not -- another. The String gives information about the source -- location of the record update. newtype () => RecUpdError RecUpdError :: String -> RecUpdError -- | This is thrown when the user calls error. The first -- String is the argument given to error, second -- String is the location. data () => ErrorCall ErrorCallWithLocation :: String -> String -> ErrorCall pattern ErrorCall :: String -> ErrorCall -- | An expression that didn't typecheck during compile time was called. -- This is only possible with -fdefer-type-errors. The String -- gives details about the failed type check. newtype () => TypeError TypeError :: String -> TypeError -- | Superclass for asynchronous exceptions. data () => SomeAsyncException SomeAsyncException :: e -> SomeAsyncException -- | Asynchronous exceptions. data () => AsyncException -- | The current thread's stack exceeded its limit. Since an exception has -- been raised, the thread's stack will certainly be below its limit -- again, but the programmer should take remedial action immediately. StackOverflow :: AsyncException -- | The program's heap is reaching its limit, and the program should take -- action to reduce the amount of live data it has. Notes: -- -- HeapOverflow :: AsyncException -- | This exception is raised by another thread calling killThread, -- or by the system if it needs to terminate the thread for some reason. ThreadKilled :: AsyncException -- | This exception is raised by default in the main thread of the program -- when the user requests to terminate the program via the usual -- mechanism(s) (e.g. Control-C in the console). UserInterrupt :: AsyncException asyncExceptionToException :: Exception e => e -> SomeException asyncExceptionFromException :: Exception e => SomeException -> Maybe e -- | Thrown when the runtime system detects that the computation is -- guaranteed not to terminate. Note that there is no guarantee that the -- runtime system will notice whether any given computation is guaranteed -- to terminate or not. data () => NonTermination NonTermination :: NonTermination -- | Thrown when the program attempts to call atomically, from the -- stm package, inside another call to atomically. data () => NestedAtomically NestedAtomically :: NestedAtomically -- | The thread is blocked on an MVar, but there are no other -- references to the MVar so it can't ever continue. data () => BlockedIndefinitelyOnMVar BlockedIndefinitelyOnMVar :: BlockedIndefinitelyOnMVar -- | The thread is waiting to retry an STM transaction, but there are no -- other references to any TVars involved, so it can't ever -- continue. data () => BlockedIndefinitelyOnSTM BlockedIndefinitelyOnSTM :: BlockedIndefinitelyOnSTM -- | This thread has exceeded its allocation limit. See -- setAllocationCounter and enableAllocationLimit. data () => AllocationLimitExceeded AllocationLimitExceeded :: AllocationLimitExceeded -- | Compaction found an object that cannot be compacted. Functions cannot -- be compacted, nor can mutable objects or pinned objects. See -- compact. newtype () => CompactionFailed CompactionFailed :: String -> CompactionFailed -- | There are no runnable threads, so the program is deadlocked. The -- Deadlock exception is raised in the main thread only. data () => Deadlock Deadlock :: Deadlock -- | If the first argument evaluates to True, then the result is the -- second argument. Otherwise an AssertionFailed exception is -- raised, containing a String with the source file and line -- number of the call to assert. -- -- Assertions can normally be turned on or off with a compiler flag (for -- GHC, assertions are normally on unless optimisation is turned on with -- -O or the -fignore-asserts option is given). When -- assertions are turned off, the first argument to assert is -- ignored, and the second argument is returned as the result. assert :: Bool -> a -> a -- | 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 -- Effectful.Exception module are for. -- -- 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 Effectful.Exception qualified 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 Control.Monad.State.Strict qualified as T
--   
--   >>> import Control.Monad.Except qualified 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 :: Type) :: Effect -- | Handle errors of type e. runError :: forall e es a. HasCallStack => Eff (Error e : es) a -> Eff es (Either (CallStack, e) a) -- | Handle errors of type e with a specific error handler. runErrorWith :: HasCallStack => (CallStack -> e -> Eff es a) -> Eff (Error e : es) a -> Eff es a -- | Handle errors of type e. In case of an error discard the -- CallStack. runErrorNoCallStack :: forall e es a. HasCallStack => Eff (Error e : es) a -> Eff es (Either e a) -- | Handle errors of type e with a specific error handler. In -- case of an error discard the CallStack. runErrorNoCallStackWith :: HasCallStack => (e -> Eff es a) -> Eff (Error e : es) a -> Eff es a -- | Throw an error of type e and specify a display function in -- case a third-party code catches the internal exception and -- shows it. throwErrorWith :: forall e es a. (HasCallStack, Error e :> es) => (e -> String) -> e -> Eff es a -- | Throw an error of type e with show as a display -- function. throwError :: forall e es a. (HasCallStack, Error e :> es, Show e) => e -> Eff es a -- | Throw an error of type e with no display function. throwError_ :: forall e es a. (HasCallStack, Error e :> es) => e -> Eff es a -- | Handle an error of type e. catchError :: forall e es a. (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 :: forall e es a. (HasCallStack, 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. (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 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 -- | 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 :: Effect) (es :: [Effect]) = forall a localEs. (HasCallStack, e :> localEs) => -- | Capture of the local environment for handling local 'Eff' computations -- when @e@ is a higher order effect. LocalEnv localEs es -> -- | The operation. e (Eff localEs) a -> Eff es a -- | Interpret an effect. -- -- Note: interpret can be turned into a reinterpret -- with the use of inject. interpret :: (HasCallStack, DispatchOf e ~ Dynamic) => EffectHandler e es -> Eff (e : es) a -> Eff es a -- | interpret with the effect handler as the last argument. interpretWith :: (HasCallStack, DispatchOf e ~ Dynamic) => Eff (e : es) a -> EffectHandler e es -> Eff es a -- | Interpret an effect using other, private effects. -- --
--   interpretreinterpret id
--   
reinterpret :: (HasCallStack, DispatchOf e ~ Dynamic) => (Eff handlerEs a -> Eff es b) -> EffectHandler e handlerEs -> Eff (e : es) a -> Eff es b -- | reinterpret with the effect handler as the last argument. reinterpretWith :: (HasCallStack, DispatchOf e ~ Dynamic) => (Eff handlerEs a -> Eff es b) -> Eff (e : es) a -> EffectHandler e handlerEs -> 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
--       Op1 :: E m ()
--       Op2 :: E m ()
--     type instance DispatchOf E = Dynamic
--   :}
--   
-- --
--   >>> :{
--     runE :: IOE :> es => Eff (E : es) a -> Eff es a
--     runE = interpret_ $ \case
--       Op1 -> liftIO (putStrLn "op1")
--       Op2 -> liftIO (putStrLn "op2")
--   :}
--   
-- --
--   >>> runEff . runE $ send Op1 >> send Op2
--   op1
--   op2
--   
-- --
--   >>> :{
--     augmentOp2 :: (E :> es, IOE :> es) => Eff es a -> Eff es a
--     augmentOp2 = interpose_ $ \case
--       Op1 -> send Op1
--       Op2 -> liftIO (putStrLn "augmented op2") >> send Op2
--   :}
--   
-- --
--   >>> runEff . runE . augmentOp2 $ send Op1 >> send Op2
--   op1
--   augmented op2
--   op2
--   
-- -- Note: when using interpose to modify only specific -- operations of the effect, your first instinct might be to match on -- them, then handle the rest with a generic match. Unfortunately, this -- doesn't work out of the box: -- --
--   >>> :{
--     genericAugmentOp2 :: (E :> es, IOE :> es) => Eff es a -> Eff es a
--     genericAugmentOp2 = interpose_ $ \case
--       Op2 -> liftIO (putStrLn "augmented op2") >> send Op2
--       op  -> send op
--   :}
--   ...
--   ...Couldn't match type ‘localEs’ with ‘es’
--   ...
--   
-- -- This is because within the generic match, send expects Op -- (Eff es) a, but op has a type Op (Eff localEs) -- a. If the effect in question is first order (i.e. its m -- type parameter is phantom), you can use coerce: -- --
--   >>> import Data.Coerce
--   
--   >>> :{
--     genericAugmentOp2 :: (E :> es, IOE :> es) => Eff es a -> Eff es a
--     genericAugmentOp2 = interpose_ $ \case
--       Op2 -> liftIO (putStrLn "augmented op2") >> send Op2
--       op  -> send @E (coerce op)
--   :}
--   
-- --
--   >>> runEff . runE . genericAugmentOp2 $ send Op1 >> send Op2
--   op1
--   augmented op2
--   op2
--   
-- -- On the other hand, when dealing with higher order effects you need to -- pattern match on each operation and unlift where necessary. interpose :: forall e es a. (HasCallStack, DispatchOf e ~ Dynamic, e :> es) => EffectHandler e es -> Eff es a -> Eff es a -- | interpose with the effect handler as the last argument. interposeWith :: (HasCallStack, DispatchOf e ~ Dynamic, e :> es) => Eff es a -> EffectHandler e es -> 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. (HasCallStack, DispatchOf e ~ Dynamic, e :> es) => (Eff handlerEs a -> Eff es b) -> EffectHandler e handlerEs -> Eff es a -> Eff es b -- | impose with the effect handler as the last argument. imposeWith :: (HasCallStack, DispatchOf e ~ Dynamic, e :> es) => (Eff handlerEs a -> Eff es b) -> Eff es a -> EffectHandler e handlerEs -> 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 -- | Create a local lifting function with the SeqUnlift strategy. -- For the general version see localLift. localSeqLift :: (HasCallStack, SharedSuffix es handlerEs) => LocalEnv localEs handlerEs -> ((forall r. Eff es r -> Eff localEs r) -> Eff es a) -> Eff es a -- | Create a local lifting function with the given strategy. localLift :: (HasCallStack, SharedSuffix es handlerEs) => LocalEnv localEs handlerEs -> UnliftStrategy -> ((forall r. Eff es r -> Eff localEs r) -> Eff es 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 -- | Lend effects to the local environment. -- -- Consider the following effect: -- --
--   >>> :{
--     data D :: Effect where
--       D :: D m ()
--     type instance DispatchOf D = Dynamic
--   :}
--   
-- -- and an auxiliary effect that requires both IOE and D -- to run: -- --
--   >>> :{
--     data E :: Effect
--     runE :: (IOE :> es, D :> es) => Eff (E : es) a -> Eff es a
--     runE = error "runE"
--   :}
--   
-- -- Trying to use runE inside the handler of D doesn't -- work out of the box: -- --
--   >>> :{
--     runD :: IOE :> es => Eff (D : es) a -> Eff es a
--     runD = interpret $ \env -> \case
--       D -> localSeqUnlift env $ \unlift -> do
--         unlift . runE $ pure ()
--   :}
--   ...
--   ...Could not deduce ...IOE :> localEs... arising from a use of ‘runE’
--   ...from the context: IOE :> es
--   ...
--   
-- -- The problem is that runE needs IOE :> localEs, -- but only IOE :> es is available. This function allows us -- to bridge the gap: -- --
--   >>> :{
--     runD :: IOE :> es => Eff (D : es) a -> Eff es a
--     runD = interpret $ \env -> \case
--       D -> localSeqUnlift env $ \unlift -> do
--         localSeqLend @'[IOE] env $ \useIOE -> do
--           unlift . useIOE . runE $ pure ()
--   :}
--   
localSeqLend :: forall lentEs es handlerEs localEs a. (HasCallStack, KnownSubset lentEs es, SharedSuffix es handlerEs) => LocalEnv localEs handlerEs -> ((forall r. Eff (lentEs ++ localEs) r -> Eff localEs r) -> Eff es a) -> Eff es a -- | Lend effects to the local environment with a given unlifting strategy. -- -- Generalizes localSeqLend. localLend :: forall lentEs es handlerEs localEs a. (HasCallStack, KnownSubset lentEs es, SharedSuffix es handlerEs) => LocalEnv localEs handlerEs -> UnliftStrategy -> ((forall r. Eff (lentEs ++ localEs) r -> Eff localEs r) -> Eff es a) -> Eff es a -- | Borrow effects from the local environment. localSeqBorrow :: forall borrowedEs es handlerEs localEs a. (HasCallStack, KnownSubset borrowedEs localEs, SharedSuffix es handlerEs) => LocalEnv localEs handlerEs -> ((forall r. Eff (borrowedEs ++ es) r -> Eff es r) -> Eff es a) -> Eff es a -- | Borrow effects from the local environment with a given unlifting -- strategy. -- -- Generalizes localSeqBorrow. localBorrow :: forall borrowedEs es handlerEs localEs a. (HasCallStack, KnownSubset borrowedEs localEs, SharedSuffix es handlerEs) => LocalEnv localEs handlerEs -> UnliftStrategy -> ((forall r. Eff (borrowedEs ++ es) r -> Eff es r) -> Eff es 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]) -- | Provide evidence that subEs is a known subset of es. class Subset subEs es => KnownSubset (subEs :: [Effect]) (es :: [Effect]) -- | Type signature of a first order effect handler. type EffectHandler_ (e :: Effect) (es :: [Effect]) = forall a localEs. HasCallStack => -- | The operation. e (Eff localEs) a -> Eff es a -- | interpret for first order effects. interpret_ :: (HasCallStack, DispatchOf e ~ Dynamic) => EffectHandler_ e es -> Eff (e : es) a -> Eff es a -- | interpretWith for first order effects. interpretWith_ :: (HasCallStack, DispatchOf e ~ Dynamic) => Eff (e : es) a -> EffectHandler_ e es -> Eff es a -- | reinterpret for first order effects. reinterpret_ :: (HasCallStack, DispatchOf e ~ Dynamic) => (Eff handlerEs a -> Eff es b) -> EffectHandler_ e handlerEs -> Eff (e : es) a -> Eff es b -- | reinterpretWith for first order effects. reinterpretWith_ :: (HasCallStack, DispatchOf e ~ Dynamic) => (Eff handlerEs a -> Eff es b) -> Eff (e : es) a -> EffectHandler_ e handlerEs -> Eff es b -- | interpose for first order effects. interpose_ :: (HasCallStack, DispatchOf e ~ Dynamic, e :> es) => EffectHandler_ e es -> Eff es a -> Eff es a -- | interposeWith for first order effects. interposeWith_ :: (HasCallStack, DispatchOf e ~ Dynamic, e :> es) => Eff es a -> EffectHandler_ e es -> Eff es a -- | impose for first order effects. impose_ :: (HasCallStack, DispatchOf e ~ Dynamic, e :> es) => (Eff handlerEs a -> Eff es b) -> EffectHandler_ e handlerEs -> Eff es a -> Eff es b -- | imposeWith for first order effects. imposeWith_ :: (HasCallStack, DispatchOf e ~ Dynamic, e :> es) => (Eff handlerEs a -> Eff es b) -> Eff es a -> EffectHandler_ e handlerEs -> 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 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 '[] '[] -- | Provider of the MonadFail instance for Eff. module Effectful.Fail -- | Provide the ability to use the MonadFail instance for -- Eff. data Fail :: Effect [Fail] :: String -> Fail m a -- | Run the Fail effect via Error. runFail :: HasCallStack => Eff (Fail : es) a -> Eff es (Either String a) -- | Run the Fail effect via the MonadFail instance for -- IO. runFailIO :: (HasCallStack, 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 [ThrowErrorWith] :: (e -> String) -> 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 :: HasCallStack => Eff (Error e : es) a -> Eff es (Either (CallStack, e) a) -- | Handle errors of type e (via Effectful.Error.Static) -- with a specific error handler. runErrorWith :: HasCallStack => (CallStack -> e -> Eff es a) -> Eff (Error e : es) a -> Eff es a -- | Handle errors of type e (via Effectful.Error.Static). -- In case of an error discard the CallStack. runErrorNoCallStack :: HasCallStack => Eff (Error e : es) a -> Eff es (Either e a) -- | Handle errors of type e (via Effectful.Error.Static) -- with a specific error handler. In case of an error discard the -- CallStack. runErrorNoCallStackWith :: HasCallStack => (e -> Eff es a) -> Eff (Error e : es) a -> Eff es a -- | Throw an error of type e and specify a display function in -- case a third-party code catches the internal exception and -- shows it. throwErrorWith :: (HasCallStack, Error e :> es) => (e -> String) -> e -> Eff es a -- | Throw an error of type e with show as a display -- function. throwError :: (HasCallStack, Error e :> es, Show e) => e -> Eff es a -- | Throw an error of type e with no display function. 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 :: (HasCallStack, 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 -- | Labeled effects. -- -- Any effect can be assigned multiple labels so you have more than one -- available simultaneously. module Effectful.Labeled -- | Assign a label to an effect. -- -- The constructor is for sending labeled operations of a dynamically -- dispatched effect to the handler: -- --
--   >>> import Effectful.Dispatch.Dynamic
--   
-- --
--   >>> :{
--     data X :: Effect where
--       X :: X m Int
--     type instance DispatchOf X = Dynamic
--   :}
--   
-- --
--   >>> :{
--     runPureEff . runLabeled @"x" (interpret_ $ \X -> pure 333) $ do
--       send $ Labeled @"x" X
--   :}
--   333
--   
newtype Labeled (label :: k) (e :: Effect) :: Effect [Labeled] :: forall label e m a. e m a -> Labeled label e m a -- | Run a Labeled effect with a given effect handler. runLabeled :: forall label e es a b. HasCallStack => (Eff (e : es) a -> Eff es b) -> Eff (Labeled label e : es) a -> Eff es b -- | Bring an effect into scope without a label. -- -- Useful for running code written with the non-labeled effect in mind. labeled :: forall label e es a. (HasCallStack, Labeled label e :> es) => Eff (e : es) a -> Eff es a -- | Convenience functions for the Labeled Error effect. module Effectful.Labeled.Error -- | Provide the ability to handle errors of type e. data Error e :: Effect [ThrowErrorWith] :: (e -> String) -> 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 :: forall label e es a. HasCallStack => Eff (Labeled label (Error e) : es) a -> Eff es (Either (CallStack, e) a) -- | Handle errors of type e (via Effectful.Error.Static) -- with a specific error handler. runErrorWith :: forall label e es a. HasCallStack => (CallStack -> e -> Eff es a) -> Eff (Labeled label (Error e) : es) a -> Eff es a -- | Handle errors of type e (via Effectful.Error.Static). -- In case of an error discard the CallStack. runErrorNoCallStack :: forall label e es a. HasCallStack => Eff (Labeled label (Error e) : es) a -> Eff es (Either e a) -- | Handle errors of type e (via Effectful.Error.Static) -- with a specific error handler. In case of an error discard the -- CallStack. runErrorNoCallStackWith :: forall label e es a. HasCallStack => (e -> Eff es a) -> Eff (Labeled label (Error e) : es) a -> Eff es a -- | Throw an error of type e and specify a display function in -- case a third-party code catches the internal exception and -- shows it. throwErrorWith :: forall label e es a. (HasCallStack, Labeled label (Error e) :> es) => (e -> String) -> e -> Eff es a -- | Throw an error of type e with show as a display -- function. throwError :: forall label e es a. (HasCallStack, Labeled label (Error e) :> es, Show e) => e -> Eff es a -- | Throw an error of type e with no display function. throwError_ :: forall label e es a. (HasCallStack, Labeled label (Error e) :> es) => e -> Eff es a -- | Handle an error of type e. catchError :: forall label e es a. (HasCallStack, Labeled label (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 label e es a. (HasCallStack, Labeled label (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 label e es a. (HasCallStack, Labeled label (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 for 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 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. -- -- Note: state modifications are rolled back on Empty only. -- In particular, they are not rolled back on exceptions. 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 :: HasCallStack => 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 <|> with the HasCallStack -- constraint for tracking purposes. plusEff :: (HasCallStack, NonDet :> es) => Eff es a -> Eff es a -> Eff es a infixl 3 `plusEff` -- | 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 instance GHC.Show.Show Effectful.NonDet.ErrorEmpty -- | 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 :: (HasCallStack, IOE :> es) => Eff (Prim : es) a -> Eff es a -- | Turn an effect handler into an effectful operation. module Effectful.Provider -- | Provide a way to run a handler of e with a given -- input. -- -- Note: f can be used to alter the return type of the -- effect handler. If that's unnecessary, use Provider_. data Provider (e :: Effect) (input :: Type) (f :: Type -> Type) :: Effect -- | A restricted variant of Provider with unchanged return type of -- the effect handler. type Provider_ e input = Provider e input Identity -- | Run the Provider effect with a given effect handler. runProvider :: HasCallStack => (forall r. HasCallStack => input -> Eff (e : es) r -> Eff es (f r)) -> Eff (Provider e input f : es) a -> Eff es a -- | Run the Provider effect with a given effect handler that -- doesn't change its return type. runProvider_ :: HasCallStack => (forall r. HasCallStack => input -> Eff (e : es) r -> Eff es r) -> Eff (Provider_ e input : es) a -> Eff es a -- | Run the effect handler. provide :: (HasCallStack, Provider e () f :> es) => Eff (e : es) a -> Eff es (f a) -- | Run the effect handler with unchanged return type. provide_ :: (HasCallStack, Provider_ e () :> es) => Eff (e : es) a -> Eff es a -- | Run the effect handler with a given input. provideWith :: (HasCallStack, Provider e input f :> es) => input -> Eff (e : es) a -> Eff es (f a) -- | Run the effect handler that doesn't change its return type with a -- given input. provideWith_ :: (HasCallStack, Provider_ e input :> es) => input -> Eff (e : es) a -> Eff es a -- | Turn a handler of multiple effects into an effectful operation. -- -- Generalizes Effectful.Provider. module Effectful.Provider.List -- | Provide a way to run a handler of multiple providedEs with a -- given input. -- -- Note: f can be used to alter the return type of the -- handler. If that's unnecessary, use ProviderList_. data ProviderList (providedEs :: [Effect]) (input :: Type) (f :: Type -> Type) :: Effect -- | A restricted variant of ProviderList with unchanged return type -- of the handler. type ProviderList_ providedEs input = ProviderList providedEs input Identity -- | Run the ProviderList effect with a given handler. runProviderList :: (HasCallStack, KnownEffects providedEs) => (forall r. HasCallStack => input -> Eff (providedEs ++ es) r -> Eff es (f r)) -> Eff (ProviderList providedEs input f : es) a -> Eff es a -- | Run the Provider effect with a given handler that doesn't -- change its return type. runProviderList_ :: (HasCallStack, KnownEffects providedEs) => (forall r. HasCallStack => input -> Eff (providedEs ++ es) r -> Eff es r) -> Eff (ProviderList_ providedEs input : es) a -> Eff es a -- | Run the handler. provideList :: forall providedEs f es a. (HasCallStack, ProviderList providedEs () f :> es) => Eff (providedEs ++ es) a -> Eff es (f a) -- | Run the handler with unchanged return type. provideList_ :: forall providedEs es a. (HasCallStack, ProviderList_ providedEs () :> es) => Eff (providedEs ++ es) a -> Eff es a -- | Run the handler with a given input. provideListWith :: forall providedEs input f es a. (HasCallStack, ProviderList providedEs input f :> es) => input -> Eff (providedEs ++ es) a -> Eff es (f a) -- | Run the handler that doesn't change its return type with a given -- input. provideListWith_ :: forall providedEs input es a. (HasCallStack, ProviderList_ providedEs input :> es) => input -> Eff (providedEs ++ es) a -> Eff es a -- | Append two type-level lists together. type family (xs :: [Effect]) ++ (ys :: [Effect]) :: [Effect] infixr 5 ++ -- | Calculate length of a list of known effects. class KnownEffects (es :: [Effect]) -- | 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 :: Type) :: Effect -- | Run a Reader effect with the given initial environment. runReader :: HasCallStack => r -> Eff (Reader r : es) a -> Eff es a -- | Execute a computation in a modified environment. withReader :: HasCallStack => (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 -- | 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 :: HasCallStack => r -> Eff (Reader r : es) a -> Eff es a -- | Execute a computation in a modified environment. withReader :: HasCallStack => (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 -- | Convenience functions for the Labeled Reader effect. module Effectful.Labeled.Reader 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 :: forall label r es a. HasCallStack => r -> Eff (Labeled label (Reader r) : es) a -> Eff es a -- | Fetch the value of the environment. ask :: forall label r es. (HasCallStack, Labeled label (Reader r) :> es) => Eff es r -- | Retrieve a function of the current environment. -- --
--   asks f ≡ f <$> ask
--   
asks :: forall label r es a. (HasCallStack, Labeled label (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 :: forall label r es a. (HasCallStack, Labeled label (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 Control.Exception (ErrorCall)
--   
--   >>> import Control.Monad.Catch
--   
--   >>> import Control.Monad.Trans.State.Strict qualified 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 :: Type) :: Effect -- | Run the State effect with the given initial state and return -- the final value along with the final state. runState :: HasCallStack => 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 :: HasCallStack => 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 :: HasCallStack => 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 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 Control.Exception (ErrorCall)
--   
--   >>> import Control.Monad.Catch
--   
--   >>> import Control.Monad.Trans.State.Strict qualified 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 :: Type) :: Effect -- | Run the State effect with the given initial state and return -- the final value along with the final state. runState :: HasCallStack => 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 :: HasCallStack => 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 :: HasCallStack => 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 :: HasCallStack => 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 :: HasCallStack => 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 :: HasCallStack => MVar' 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. -- -- Note: this function gets an exclusive access to the state for -- its duration. state :: (HasCallStack, 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 :: (HasCallStack, 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 :: (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)
--   
-- -- Note: this function gets an exclusive access to the state for -- its duration. modifyM :: (HasCallStack, 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 :: HasCallStack => 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 :: HasCallStack => 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 :: HasCallStack => 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 :: HasCallStack => 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 :: HasCallStack => 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 :: HasCallStack => 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 () -- | Convenience functions for the Labeled State effect. module Effectful.Labeled.State -- | 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 :: forall label s es a. HasCallStack => s -> Eff (Labeled label (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 :: forall label s es a. HasCallStack => s -> Eff (Labeled label (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 :: forall label s es a. HasCallStack => s -> Eff (Labeled label (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 :: forall label s es a. HasCallStack => s -> Eff (Labeled label (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 :: forall label s es a. HasCallStack => s -> Eff (Labeled label (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 :: forall label s es a. HasCallStack => s -> Eff (Labeled label (State s) : es) a -> Eff es s -- | Fetch the current value of the state. get :: forall label s es. (HasCallStack, Labeled label (State s) :> es) => Eff es s -- | Get a function of the current state. -- --
--   gets f ≡ f <$> get
--   
gets :: forall label s es a. (HasCallStack, Labeled label (State s) :> es) => (s -> a) -> Eff es a -- | Set the current state to the given value. put :: forall label s es. (HasCallStack, Labeled label (State s) :> es) => s -> Eff es () -- | Apply the function to the current state and return a value. state :: forall label s es a. (HasCallStack, Labeled label (State s) :> es) => (s -> (a, s)) -> Eff es a -- | Apply the function to the current state. -- --
--   modify f ≡ state (\s -> ((), f s))
--   
modify :: forall label s es. (HasCallStack, Labeled label (State s) :> es) => (s -> s) -> Eff es () -- | Apply the monadic function to the current state and return a value. stateM :: forall label s es a. (HasCallStack, Labeled label (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 :: forall label s es. (HasCallStack, Labeled label (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 :: Type) :: Effect -- | Run a Writer effect and return the final value along with the -- final output. runWriter :: (HasCallStack, 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 :: (HasCallStack, 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, 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 :: (HasCallStack, 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 :: (HasCallStack, 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 :: Type) :: Effect -- | Run a Writer effect and return the final value along with the -- final output. runWriter :: (HasCallStack, 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 :: (HasCallStack, 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, 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 :: (HasCallStack, 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 :: (HasCallStack, 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 :: (HasCallStack, 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 :: (HasCallStack, 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 :: (HasCallStack, 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 :: (HasCallStack, 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) -- | Convenience functions for the Labeled Writer effect. module Effectful.Labeled.Writer -- | 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 :: forall label w es a. (HasCallStack, Monoid w) => Eff (Labeled label (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 :: forall label w es a. (HasCallStack, Monoid w) => Eff (Labeled label (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 :: forall label w es a. (HasCallStack, Monoid w) => Eff (Labeled label (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 :: forall label w es a. (HasCallStack, Monoid w) => Eff (Labeled label (Writer w) : es) a -> Eff es w -- | Append the given output to the overall output of the Writer. tell :: forall label w es. (HasCallStack, Labeled label (Writer w) :> es) => w -> Eff es () -- | Execute an action and append its output to the overall output of the -- Writer. listen :: forall label w es a. (HasCallStack, Labeled label (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 :: forall label w es a b. (HasCallStack, Labeled label (Writer w) :> es) => (w -> b) -> Eff es a -> Eff es (a, b)