-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Extensional capabilities and deriving combinators -- -- Standard capability type classes for extensional effects and -- combinators to derive capability instances with little boilerplate. @package capability @version 0.5.0.0 -- | A capability is a type class over a monad which specifies the effects -- that a function is allowed to perform. Capabilities differ from -- traditional monad transformer type classes in that they are completely -- independent of the way the monad is constructed. A state capability -- can for instance be implemented as a lens on a field in a larger state -- monad, or an error capability could provide for throwing only a subset -- of the errors of an error monad. -- -- This library defines several standard, reusable capabilities that -- replace the mtl's monad-transformer type classes. Because capabilities -- are not tied to a particular implementation of the monad, they cannot -- be discharged by instance resolution. Instead this library provides -- combinators in the form of newtypes with instances, to be used with -- deriving-via. To learn about deriving via, watch Baldur Blondal's -- introductory video -- https://skillsmatter.com/skillscasts/10934-lightning-talk-stolen-instances-taste-just-fine. -- -- By way of comparison, with the mtl you would write something like -- --
-- foo :: (MonadReader E, MonadState S) => a -> m () ---- -- You can use foo at type a -> ReaderT E (State S). -- But you can't use foo with the ReaderT pattern -- https://www.fpcomplete.com/blog/2017/06/readert-design-pattern. -- With this library, you would instead have: -- --
-- foo :: (HasReader "conf" E, HasState "st" S) => a -> m () ---- -- Where "conf" and "st" are the names (also referred -- to as tags) of the capabilities demanded by foo. Contrary to the mtl, -- capabilities are named, rather than disambiguated by the type of their -- implied state, or exception. This makes it easy to have multiple state -- capabilities. -- -- To provide these capabilities, for instance with the ReaderT -- pattern, do as follows (for a longer form tutorial, check the -- README): -- --
-- newtype MyM a = MyM (ReaderT (E, IORef s)) -- deriving (Functor, Applicative, Monad) -- deriving (HasState "st" Int) via -- ReaderIORef (Rename 2 (Pos 2 () -- (MonadReader (ReaderT (E, IORef s) IO)))) -- deriving (HasReader "conf" Int) via -- (Rename 1 (Pos 1 () -- (MonadReader (ReaderT (E, IORef s) IO)))) ---- -- Then you can use foo at type MyM. Or any other type -- which can provide these capabilites. -- --
-- f :: HasReader "config" Config m => … ---- -- over and over again. -- -- To avoid this, each capability comes with a functional—here -- HasReader'—variant (in this terminology HasReader is -- relational). Where the type is deduced from the capability's -- name. The mapping from name to type is done with the -- TypeOf family, which is re-exported by every -- capability module. -- --
-- type instance TypeOf Symbol "config" = Config -- -- f :: HasReader' "config" m => … ---- --
-- Source Sink -- / \ / \ -- / \ / \ -- Reader State Writer ---- -- Capability.Source and Capability.Sink have just a method -- each, and no laws. The bottom three, familiar from mtl, add methods -- and laws relating them. The use of tags allows one to have independent -- effects that share a superclass. E.g. HasState "foo" Int and -- HasWriter "bar" String. -- -- Finally there are -- --
-- data Conf -- -- foo :: HasReader Conf C => m () ---- -- This way, Conf can be qualified in case of a name conflict -- with another library. module Capability -- | Defines newtypes that serve as combinators to compose -- deriving via strategies. module Capability.Accessors -- | Coerce the type in the context m to to. -- -- Example: -- --
-- newtype MyInt = MyInt Int -- newtype MyReader a = MyReader (Reader Int a) -- deriving (HasReader "a" MyInt) via -- Coerce MyInt (MonadReader (Reader Int)) ---- -- Converts the HasReader "a" Int instance of -- MonadReader (Reader Int) to a HasReader "a" -- MyInt instance using Coercible Int MyInt. newtype Coerce (to :: Type) m (a :: Type) Coerce :: m a -> Coerce (to :: Type) m (a :: Type) -- | Rename the tag. -- -- Example: -- --
-- newtype MyReader a = MyReader (Reader Int a) -- deriving (HasReader "foo" Int) via -- Rename "bar" (MonadReader (Reader Int)) ---- -- Converts the HasReader "bar" Int instance of -- MonadReader (Reader Int) to a HasReader -- "foo" Int instance by renaming the tag. -- -- Note, that MonadReader itself does not fix a tag, and -- Rename is redundant in this example. -- -- See Pos below for a common use-case. newtype Rename (oldtag :: k) m (a :: Type) Rename :: m a -> Rename (oldtag :: k) m (a :: Type) -- | Access the record field field in the context m. -- -- Example: -- --
-- data Foo = Foo { foo :: Int }
-- newtype MyReader a = MyReader (Reader Foo a)
-- deriving (HasReader "foo" Int) via
-- Field "foo" () (MonadReader (Reader Foo))
--
--
-- Converts the HasReader () Foo instance of
-- MonadReader (Reader Foo) to a HasReader
-- "foo" Int instance by focusing on the field foo in the
-- Foo record.
--
-- See Rename for a way to change the tag.
newtype Field (field :: Symbol) (oldtag :: k) m (a :: Type)
Field :: m a -> Field (field :: Symbol) (oldtag :: k) m (a :: Type)
-- | Access the value at position pos in the context m.
--
-- Example:
--
-- -- newtype MyReader a = MyReader (Reader (Int, Bool) a) -- deriving (HasReader 1 Int) via -- Pos 1 () (MonadReader (Reader (Int, Bool))) ---- -- Converts the HasReader () (Int, Bool) instance of -- MonadReader (Reader (Int, Bool)) to a -- HasReader 1 Int instance by focusing on the first -- element of the tuple. -- -- The implied number tag can be renamed to a more descriptive name using -- the Rename combinator: -- --
-- newtype MyReader a = MyReader (Reader (Int, Bool) a) -- deriving (HasReader "foo" Int) via -- Rename 1 (Pos 1 () (MonadReader (Reader (Int, Bool)))) --newtype Pos (pos :: Nat) (oldtag :: k) m (a :: Type) Pos :: m a -> Pos (pos :: Nat) (oldtag :: k) m (a :: Type) -- | Choose the given constructor in the sum-type in context m. -- -- Example: -- --
-- data MyError = ErrA String | ErrB String -- newtype MyExcept a = MyExcept (ExceptT MyError Identity a) -- deriving (HasThrow "ErrB" String) via -- Ctor "ErrB" () (MonadError (ExceptT MyError Identity)) ---- -- Converts the HasThrow () "MyError" instance of -- MonadError (ExceptT MyError Identity) to a -- HasThrow "ErrB" String instance by wrapping thrown -- Strings in the ErrB constructor. newtype Ctor (ctor :: Symbol) (oldtag :: k) m (a :: Type) Ctor :: m a -> Ctor (ctor :: Symbol) (oldtag :: k) m (a :: Type) -- | Skip one level in a monad transformer stack. -- -- Note, that instances generated with this strategy can incur a -- performance penalty. -- -- Example: -- --
-- newtype MyStates a = MyStates (StateT Int (State Bool) a) -- deriving (HasState "foo" Bool) via -- Lift (StateT Int (MonadState (State Bool))) ---- -- Uses the MonadTrans instance of StateT Int to lift the -- HasState "foo" Bool instance of the underlying -- MonadState (State Bool) over the StateT Int -- monad transformer. newtype Lift m (a :: Type) Lift :: m a -> Lift m (a :: Type) -- | Compose two accessors. -- -- This is not necessary in deriving via clauses, but in places where a -- transformer is expected as a type argument. E.g. wrapError. newtype (:.:) (t2 :: (Type -> Type) -> Type -> Type) (t1 :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) (a :: Type) (:.:) :: m a -> (:.:) (t2 :: (Type -> Type) -> Type -> Type) (t1 :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) (a :: Type) infixr 9 :.: infixr 9 :.: instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Capability.Accessors.Coerce to m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Capability.Accessors.Coerce to m) instance GHC.Base.Monad m => GHC.Base.Monad (Capability.Accessors.Coerce to m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Capability.Accessors.Coerce to m) instance GHC.Base.Functor m => GHC.Base.Functor (Capability.Accessors.Coerce to m) instance forall k (oldtag :: k) (m :: * -> *). Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Capability.Accessors.Rename oldtag m) instance forall k (oldtag :: k) (m :: * -> *). Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Capability.Accessors.Rename oldtag m) instance forall k (oldtag :: k) (m :: * -> *). GHC.Base.Monad m => GHC.Base.Monad (Capability.Accessors.Rename oldtag m) instance forall k (oldtag :: k) (m :: * -> *). GHC.Base.Applicative m => GHC.Base.Applicative (Capability.Accessors.Rename oldtag m) instance forall k (oldtag :: k) (m :: * -> *). GHC.Base.Functor m => GHC.Base.Functor (Capability.Accessors.Rename oldtag m) instance forall (field :: GHC.Types.Symbol) k (oldtag :: k) (m :: * -> *). Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Capability.Accessors.Field field oldtag m) instance forall (field :: GHC.Types.Symbol) k (oldtag :: k) (m :: * -> *). Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Capability.Accessors.Field field oldtag m) instance forall (field :: GHC.Types.Symbol) k (oldtag :: k) (m :: * -> *). GHC.Base.Monad m => GHC.Base.Monad (Capability.Accessors.Field field oldtag m) instance forall (field :: GHC.Types.Symbol) k (oldtag :: k) (m :: * -> *). GHC.Base.Applicative m => GHC.Base.Applicative (Capability.Accessors.Field field oldtag m) instance forall (field :: GHC.Types.Symbol) k (oldtag :: k) (m :: * -> *). GHC.Base.Functor m => GHC.Base.Functor (Capability.Accessors.Field field oldtag m) instance forall (pos :: GHC.Types.Nat) k (oldtag :: k) (m :: * -> *). Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Capability.Accessors.Pos pos oldtag m) instance forall (pos :: GHC.Types.Nat) k (oldtag :: k) (m :: * -> *). Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Capability.Accessors.Pos pos oldtag m) instance forall (pos :: GHC.Types.Nat) k (oldtag :: k) (m :: * -> *). GHC.Base.Monad m => GHC.Base.Monad (Capability.Accessors.Pos pos oldtag m) instance forall (pos :: GHC.Types.Nat) k (oldtag :: k) (m :: * -> *). GHC.Base.Applicative m => GHC.Base.Applicative (Capability.Accessors.Pos pos oldtag m) instance forall (pos :: GHC.Types.Nat) k (oldtag :: k) (m :: * -> *). GHC.Base.Functor m => GHC.Base.Functor (Capability.Accessors.Pos pos oldtag m) instance forall (ctor :: GHC.Types.Symbol) k (oldtag :: k) (m :: * -> *). Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Capability.Accessors.Ctor ctor oldtag m) instance forall (ctor :: GHC.Types.Symbol) k (oldtag :: k) (m :: * -> *). Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Capability.Accessors.Ctor ctor oldtag m) instance forall (ctor :: GHC.Types.Symbol) k (oldtag :: k) (m :: * -> *). GHC.Base.Monad m => GHC.Base.Monad (Capability.Accessors.Ctor ctor oldtag m) instance forall (ctor :: GHC.Types.Symbol) k (oldtag :: k) (m :: * -> *). GHC.Base.Applicative m => GHC.Base.Applicative (Capability.Accessors.Ctor ctor oldtag m) instance forall (ctor :: GHC.Types.Symbol) k (oldtag :: k) (m :: * -> *). GHC.Base.Functor m => GHC.Base.Functor (Capability.Accessors.Ctor ctor oldtag m) instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Capability.Accessors.Lift m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Capability.Accessors.Lift m) instance GHC.Base.Monad m => GHC.Base.Monad (Capability.Accessors.Lift m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Capability.Accessors.Lift m) instance GHC.Base.Functor m => GHC.Base.Functor (Capability.Accessors.Lift m) instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad ((Capability.Accessors.:.:) t2 t1 m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO ((Capability.Accessors.:.:) t2 t1 m) instance GHC.Base.Monad m => GHC.Base.Monad ((Capability.Accessors.:.:) t2 t1 m) instance GHC.Base.Applicative m => GHC.Base.Applicative ((Capability.Accessors.:.:) t2 t1 m) instance GHC.Base.Functor m => GHC.Base.Functor ((Capability.Accessors.:.:) t2 t1 m) -- | This module defines helper types and type families for working with -- sets of capabilities. module Capability.Constraints -- | Type family used used to express a conjunction of constraints over a -- single type. -- -- Examples: -- --
-- All '[Num, Eq] Int -- -- Equivalent to: (Num Int, Eq Int) -- -- All '[HasReader "foo" Int, HasSink "bar" Float] m -- -- Equivalent to: (HasReader "foo" Int m, HasSink "bar" Float m) --type family All (xs :: [k -> Constraint]) a :: Constraint -- | A Capability takes a type constructor Type -> Type -- (e.g., a monad) and returns a Constraint. Examples of -- capabilities includ: HasReader "foo" Int, MonadIO, … type Capability = (Type -> Type) -> Constraint -- | The kind of constraints, like Show a data Constraint -- | Values of type Dict p capture a dictionary for a -- constraint of type p. -- -- e.g. -- --
-- Dict :: Dict (Eq Int) ---- -- captures a dictionary that proves we have an: -- --
-- instance Eq 'Int ---- -- Pattern matching on the Dict constructor will bring this -- instance into scope. data Dict a [Dict] :: forall a. a => Dict a module Capability.Derive -- | Runs an action that requires additional capabilities. -- -- derive @t @derived @ambient act runs act by -- providing both the capabilities in derived and -- ambient. The difference is that ambient capabilities -- are assumed to be available, whereas derived instances are -- provided by t. -- -- derive assumes that t is a newtype defined in the -- form: -- --
-- newtype T m a = T (m a) ---- -- Then derive uses type-class instances for T to provide -- for each of the capabilities in derived. -- -- A common instance of this is wrapError, whereby exceptions -- raised by act can be repackaged in a larger exception type. -- -- The derive function is experimental and is subject to change. derive :: forall t (derived :: [Capability]) (ambient :: [Capability]) m a. (forall x. Coercible (t m x) (m x), All derived (t m), All ambient m) => (forall m'. (All derived m', All ambient m') => m' a) -> m a -- | Use this module to provide an ad-hoc interpreter for a capability -- using type class reflection. -- -- Use the functions interpret_ or interpret for ad-hoc -- interpretation of capabilities. -- -- Refer to Reflected if you would like to enable reflection for a -- new capability. -- -- More complex examples using this module can be found in the -- Reflection example module. -- -- For details on reflection refer to the tutorial at -- https://www.tweag.io/posts/2017-12-21-reflection-tutorial.html -- and the reflection library at -- https://hackage.haskell.org/package/reflection. module Capability.Reflection -- |
-- interpret_ @tag dict action ---- -- Execute action using the ad-hoc interpretation of a -- capability c under tag defined by dict, -- where dict is a value of type Reified tag c, -- i.e. a record providing the implementation of the methods of -- capability c. -- -- For example, the following provides an ad-hoc interpretation for the -- HasSource capability. -- --
-- >>> :{
-- interpret_ @"my-source"
-- ReifiedSource { _await = pure "capabilities" }
-- (replicateM 3 (await @"my-source"))
-- :}
-- ["capabilities", "capabilities", "capabilities"]
--
interpret_ :: forall tag c m a. (Monad m, forall s. Reifies s (Reified tag c m) => c (Reflected s c m)) => Reified tag c m -> (forall m'. c m' => m' a) -> m a
-- | -- interpret @tag @ambient dict action ---- -- Like interpret_ but forwards the ambient capabilities -- ambient into the context of action as well. -- -- For example, the following provides an ad-hoc interpretation for the -- HasSource capability, while using an ambient HasSink -- capability. -- --
-- >>> :{
-- interpret @"my-source" @'[HasSink "my-sink" String]
-- ReifiedSource { _await = pure "capabilities" }
-- (replicateM_ 3 (await @"my-source" >>= yield @"my-sink"))
-- :}
--
interpret :: forall tag (cs :: [Capability]) c m a. (Monad m, All cs m, forall s. Reifies s (Reified tag c m) => c (Reflected s c m)) => Reified tag c m -> (forall m'. All (c : cs) m' => m' a) -> m a
-- | -- Reified tag capability m ---- -- Defines the dictionary type for the methods of capability -- under tag in the monad m. Refer to interpret_ -- for an example use-case. -- -- For example, the HasSink capability has the method -- yield :: a -> m (). The corresponding dictionary -- type is defined as follows. -- --
-- >>> :{
-- data instance Reified tag (HasSink tag a) m =
-- ReifiedSink { _yield :: forall a. a -> m () }
-- :}
--
--
-- Superclass dictionaries are represented as nested records. For
-- example, the HasState capability has the superclasses
-- HasSource and HasSink and the method state ::
-- (s -> (a, s)) -> m a. The corresponding dictionary type is
-- defined as follows.
--
--
-- >>> :{
-- data instance Reified tag (HasState tag s) m =
-- ReifiedState
-- { _stateSource :: Reified tag (HasSource tag s) m,
-- _stateSink :: Reified tag (HasSink tag s) m,
-- _state :: forall a. (s -> (a, s)) -> m a
-- }
-- :}
--
data family Reified (tag :: k) (c :: Capability) (m :: Type -> Type)
-- | -- Reflected s capability m ---- -- Carries the type class instance for capability in the monad -- m defined by the dictionary reflected in s in the -- type system. -- -- For most use-cases it is not necessary to use this type directly. Use -- interpret_ or interpret instead. -- -- If you wish to enable reflection for a new capability, then you will -- need to define a type class instance for Reflected for the -- new capability. Note, you will also need to define an instance of -- Reified which defines the dictionary type of the new -- capability. Hint, you can use reified @s to obtain the -- dictionary from the context in the instance implementation. -- -- For example, the Reflected instance for the HasSink -- capability can be defined as follows. Assuming the dictionary -- described in Reified. -- --
-- >>> :{
-- instance
-- (Monad m, Reifies s (Reified tag (HasSink tag a) m)) =>
-- HasSink tag a (Reflected s (HasSink tag a) m)
-- where
-- yield a = Reflect $ _yield (reified @s) a
-- :}
--
newtype Reflected (s :: Type) (c :: Capability) (m :: Type -> Type) (a :: Type)
Reflect :: m a -> Reflected (s :: Type) (c :: Capability) (m :: Type -> Type) (a :: Type)
-- | -- reified @s ---- -- Obtain the dictionary that is reflected in the type system under -- s. -- -- This is a convenience wrapper around reflect. reified :: forall s tag c m. Reifies s (Reified tag c m) => Reified tag c m class Reifies (s :: k) a | s -> a -- | Reify a value at the type level, to be recovered with reflect. reify :: a -> (forall s. Reifies s a => Proxy s -> r) -> r -- | Recover a value inside a reify context, given a proxy for its -- reified type. reflect :: Reifies s a => proxy s -> a -- | Proxy is a type that holds no data, but has a phantom parameter -- of arbitrary type (or even kind). Its use is to provide type -- information, even though there is no value available of that type (or -- it may be too costly to create one). -- -- Historically, Proxy :: Proxy a is a safer -- alternative to the undefined :: a idiom. -- --
-- >>> Proxy :: Proxy (Void, Int -> Int) -- Proxy ---- -- Proxy can even hold types of higher kinds, -- --
-- >>> Proxy :: Proxy Either -- Proxy ---- --
-- >>> Proxy :: Proxy Functor -- Proxy ---- --
-- >>> Proxy :: Proxy complicatedStructure -- Proxy --data Proxy (t :: k) Proxy :: Proxy (t :: k) instance GHC.Base.Monad m => GHC.Base.Monad (Capability.Reflection.Reflected s c m) instance GHC.Base.Applicative m => GHC.Base.Applicative (Capability.Reflection.Reflected s c m) instance GHC.Base.Functor m => GHC.Base.Functor (Capability.Reflection.Reflected s c m) module Capability.TypeOf -- | Type family associating a tag to the corresponding type. It is -- intended to simplify constraint declarations, by removing the need to -- redundantly specify the type associated to a tag. -- -- It is poly-kinded, which allows users to define their own kind of -- tags. Standard haskell types can also be used as tags by specifying -- the Type kind when defining the type family instance. -- -- Defining TypeOf instances for Symbols (typelevel string -- literals) is discouraged. Since symbols all belong to the same global -- namespace, such instances could conflict with others defined in -- external libraries. More generally, as for typeclasses, TypeOf -- instances should always be defined in the same module as the tag type -- to prevent issues due to orphan instances. -- -- Example: -- --
-- import Capability.Reader -- -- data Foo -- data Bar -- type instance TypeOf Type Foo = Int -- type instance TypeOf Type Bar = String -- -- -- Same as: foo :: HasReader Foo Int M => … -- foo :: HasReader' Foo m => … -- foo = … --type family TypeOf k (s :: k) :: Type -- | Defines a capability type class for a state effect. A state capability -- provides a state which can be retrieved with get and set with -- put. As an analogy, each state capability is equivalent to -- making one IORef available in an IO computation -- (except, of course, that a state capability does not have to be -- provided by IO). -- -- This is a very expressive capability. It is often preferable to -- restrict to less powerful capabilities such as -- Capability.Reader, Capability.Writer, or -- Capability.Stream. module Capability.State -- | State capability -- -- An instance should fulfill the following laws. At this point these -- laws are not definitive, see -- https://github.com/haskell/mtl/issues/5. -- --
-- get @t >>= \s1 -> get @t >>= \s2 -> pure (s1, s2) = get @t >>= \s -> pure (s, s) ---- --
-- get @t >>= \_ -> put @t s = put @t s ---- --
-- put @t s1 >> put @t s2 = put @t s2 ---- --
-- put @t s >> get @t = put @t s >> pure s ---- --
-- state @t f = get @t >>= \s -> let (a, s') = f s in put @t s' >> pure a --class (Monad m, HasSource tag s m, HasSink tag s m) => HasState (tag :: k) (s :: Type) (m :: Type -> Type) | tag m -> s -- | For technical reasons, this method needs an extra proxy argument. You -- only need it if you are defining new instances of 'HasState. -- Otherwise, you will want to use state. See state for -- more documentation. state_ :: HasState tag s m => Proxy# tag -> (s -> (a, s)) -> m a -- | get @tag retrieve the current state of the state capability -- tag. get :: forall tag s m. HasState tag s m => m s -- | put @tag s replace the current state of the state capability -- tag with s. put :: forall tag s m. HasState tag s m => s -> m () -- | state @tag f lifts a pure state computation f to a -- monadic action in an arbitrary monad m with capability -- HasState. -- -- Given the current state s of the state capability -- tag and (a, s') = f s, update the state to -- s' and return a. state :: forall tag s m a. HasState tag s m => (s -> (a, s)) -> m a -- | modify @tag f given the current state s of the state -- capability tag and s' = f s, updates the state of -- the capability tag to s'. modify :: forall tag s m. HasState tag s m => (s -> s) -> m () -- | Same as modify but strict in the new state. modify' :: forall tag s m. HasState tag s m => (s -> s) -> m () -- | gets @tag f retrieves the image, by f of the current -- state of the state capability tag. -- --
-- gets @tag f = f <$> get @tag --gets :: forall tag s m a. HasState tag s m => (s -> a) -> m a -- | Execute the given state action on a sub-component of the current state -- as defined by the given transformer t. The set of retained -- capabilities must be passed as @cs. If no capabilities are required, -- None can be used. -- -- Examples: -- --
-- foo :: HasState "foo" Int m => m ()
-- zoom @"foo" @(Field "foo" "foobar") @None foo
-- :: (HasField' "foobar" record Int, HasState "foobar" record m) => m ()
--
-- zoom @"foo" @(Field "foo" "foobar") @('[MonadIO]) bar
-- :: ( HasField' "foobar" record Int, HasState "foobar" record m
-- , MonadIO m) => m ()
--
-- foo :: HasState "foo" Int m => m ()
-- bar :: (MonadIO m, HasState "foo" Int m) => m ()
--
--
-- Note: the HasField' constraint comes from the
-- generic-lens package.
--
-- This function is experimental and subject to change. See
-- https://github.com/tweag/capability/issues/46.
zoom :: forall innertag t (cs :: [Capability]) inner m a. (forall x. Coercible (t m x) (m x), HasState innertag inner (t m), All cs m) => (forall m'. All (HasState innertag inner : cs) m' => m' a) -> m a
-- | -- Reified tag capability m ---- -- Defines the dictionary type for the methods of capability -- under tag in the monad m. Refer to interpret_ -- for an example use-case. -- -- For example, the HasSink capability has the method -- yield :: a -> m (). The corresponding dictionary -- type is defined as follows. -- --
-- >>> :{
-- data instance Reified tag (HasSink tag a) m =
-- ReifiedSink { _yield :: forall a. a -> m () }
-- :}
--
--
-- Superclass dictionaries are represented as nested records. For
-- example, the HasState capability has the superclasses
-- HasSource and HasSink and the method state ::
-- (s -> (a, s)) -> m a. The corresponding dictionary type is
-- defined as follows.
--
--
-- >>> :{
-- data instance Reified tag (HasState tag s) m =
-- ReifiedState
-- { _stateSource :: Reified tag (HasSource tag s) m,
-- _stateSink :: Reified tag (HasSink tag s) m,
-- _state :: forall a. (s -> (a, s)) -> m a
-- }
-- :}
--
data family Reified (tag :: k) (c :: Capability) (m :: Type -> Type)
-- | Type synonym using the TypeOf type family to specify
-- HasState constraints without having to specify the type
-- associated to a tag.
type HasState' (tag :: k) = HasState tag (TypeOf k tag)
-- | Type family associating a tag to the corresponding type. It is
-- intended to simplify constraint declarations, by removing the need to
-- redundantly specify the type associated to a tag.
--
-- It is poly-kinded, which allows users to define their own kind of
-- tags. Standard haskell types can also be used as tags by specifying
-- the Type kind when defining the type family instance.
--
-- Defining TypeOf instances for Symbols (typelevel string
-- literals) is discouraged. Since symbols all belong to the same global
-- namespace, such instances could conflict with others defined in
-- external libraries. More generally, as for typeclasses, TypeOf
-- instances should always be defined in the same module as the tag type
-- to prevent issues due to orphan instances.
--
-- Example:
--
-- -- import Capability.Reader -- -- data Foo -- data Bar -- type instance TypeOf Type Foo = Int -- type instance TypeOf Type Bar = String -- -- -- Same as: foo :: HasReader Foo Int M => … -- foo :: HasReader' Foo m => … -- foo = … --type family TypeOf k (s :: k) :: Type -- | Derive HasState from m's MonadState instance. newtype MonadState (m :: Type -> Type) (a :: Type) MonadState :: m a -> MonadState (m :: Type -> Type) (a :: Type) -- | Derive a state monad from a reader over an IORef. -- -- Example: -- --
-- newtype MyState m a = MyState (ReaderT (IORef Int) m a) -- deriving (Functor, Applicative, Monad) -- deriving HasState "foo" Int via -- ReaderIORef (MonadReader (ReaderT (IORef Int) m)) ---- -- See ReaderRef for a more generic strategy. newtype ReaderIORef m a ReaderIORef :: m a -> ReaderIORef m a -- | Derive a state monad from a reader over a mutable reference. -- -- Mutable references are available in a PrimMonad. The -- corresponding PrimState has to match the MCState of the -- reference. This constraint makes a stand-alone deriving clause -- necessary. -- -- Example: -- --
-- newtype MyState m a = MyState (ReaderT (IORef Int) m a) -- deriving (Functor, Applicative, Monad) -- deriving via ReaderRef (MonadReader (ReaderT (IORef Int) m)) -- instance (PrimMonad m, PrimState m ~ PrimState IO) -- => HasState "foo" Int (MyState m) ---- -- See ReaderIORef for a specialized version over IORef. newtype ReaderRef m (a :: Type) ReaderRef :: m a -> ReaderRef m (a :: Type) -- | Defines a capability for computations that consume a stream of values -- as part of their execution. -- -- Programs comsuming streams of data are common. Examples: rolling up -- input events. Sources are similar to Python generators. -- -- This can be thought of as a reader capability where there's no -- guarantee that one reads the same value each time. -- -- The HasSource capability enables separating the logic -- responsible for emitting events from that responsible for collecting -- or handling them. The name is because a source is needed to produce -- the locally consumed stream. module Capability.Source -- | Sourcing capability. -- -- An instance does not need to fulfill any additional laws besides the -- monad laws. class Monad m => HasSource (tag :: k) (a :: Type) (m :: Type -> Type) | tag m -> a -- | For technical reasons, this method needs an extra proxy argument. You -- only need it if you are defining new instances of HasSource. -- Otherwise, you will want to use await. See await for -- more documentation. await_ :: HasSource tag a m => Proxy# tag -> m a -- | await @tag a takes a from the source capability -- tag. await :: forall tag a m. HasSource tag a m => m a -- | awaits @tag retrieves the image by f of the -- environment of the source capability tag. -- --
-- awaits @tag f = f <$> await @tag --awaits :: forall tag r m a. HasSource tag r m => (r -> a) -> m a -- | Type synonym using the TypeOf type family to specify -- HasSource constraints without having to specify the type -- associated to a tag. type HasSource' (tag :: k) = HasSource tag (TypeOf k tag) -- | Type family associating a tag to the corresponding type. It is -- intended to simplify constraint declarations, by removing the need to -- redundantly specify the type associated to a tag. -- -- It is poly-kinded, which allows users to define their own kind of -- tags. Standard haskell types can also be used as tags by specifying -- the Type kind when defining the type family instance. -- -- Defining TypeOf instances for Symbols (typelevel string -- literals) is discouraged. Since symbols all belong to the same global -- namespace, such instances could conflict with others defined in -- external libraries. More generally, as for typeclasses, TypeOf -- instances should always be defined in the same module as the tag type -- to prevent issues due to orphan instances. -- -- Example: -- --
-- import Capability.Reader -- -- data Foo -- data Bar -- type instance TypeOf Type Foo = Int -- type instance TypeOf Type Bar = String -- -- -- Same as: foo :: HasReader Foo Int M => … -- foo :: HasReader' Foo m => … -- foo = … --type family TypeOf k (s :: k) :: Type -- | Derive HasSource from m's MonadReader instance. newtype MonadReader (m :: Type -> Type) (a :: Type) MonadReader :: m a -> MonadReader (m :: Type -> Type) (a :: Type) -- | Convert a pure state monad into a reader monad. -- -- Pure meaning that the monad stack does not allow catching -- exceptions. Otherwise, an exception occurring in the action passed to -- local could cause the context to remain modified outside of -- the call to local. E.g. -- --
-- local @tag (const r') (throw MyException) -- `catch` \MyException -> ask @tag ---- -- returns r' instead of the previous value. -- -- Note, that no MonadIO instance is provided, as this would -- allow catching exceptions. -- -- See ReadState. newtype ReadStatePure (m :: Type -> Type) (a :: Type) ReadStatePure :: m a -> ReadStatePure (m :: Type -> Type) (a :: Type) -- | Convert a state monad into a reader monad. -- -- Use this if the monad stack allows catching exceptions. -- -- See ReadStatePure. newtype ReadState (m :: Type -> Type) (a :: Type) ReadState :: m a -> ReadState (m :: Type -> Type) (a :: Type) -- | Derive HasState from m's MonadState instance. newtype MonadState (m :: Type -> Type) (a :: Type) MonadState :: m a -> MonadState (m :: Type -> Type) (a :: Type) -- | Derive a state monad from a reader over an IORef. -- -- Example: -- --
-- newtype MyState m a = MyState (ReaderT (IORef Int) m a) -- deriving (Functor, Applicative, Monad) -- deriving HasState "foo" Int via -- ReaderIORef (MonadReader (ReaderT (IORef Int) m)) ---- -- See ReaderRef for a more generic strategy. newtype ReaderIORef m a ReaderIORef :: m a -> ReaderIORef m a -- | Derive a state monad from a reader over a mutable reference. -- -- Mutable references are available in a PrimMonad. The -- corresponding PrimState has to match the MCState of the -- reference. This constraint makes a stand-alone deriving clause -- necessary. -- -- Example: -- --
-- newtype MyState m a = MyState (ReaderT (IORef Int) m a) -- deriving (Functor, Applicative, Monad) -- deriving via ReaderRef (MonadReader (ReaderT (IORef Int) m)) -- instance (PrimMonad m, PrimState m ~ PrimState IO) -- => HasState "foo" Int (MyState m) ---- -- See ReaderIORef for a specialized version over IORef. newtype ReaderRef m (a :: Type) ReaderRef :: m a -> ReaderRef m (a :: Type) -- | Defines a capability for computations that produce a stream of values -- as part of their execution. -- -- Programs producing streams of data are common. Examples: emitting -- events on input, or emitting events whenever certain conditions are -- observed. streams are similar to Python generators. -- -- The HasSink capability enables separating the logic responsible -- for emitting events from that responsible for collecting or handling -- them. The name is because a sink is needed to consume the locally -- produced stream. -- -- This can be thought of as a writer capability of a list of values -- HasWriter tag [v] with \x -> tell @tag [x] as a -- primitive operation. However, that implementation would be -- inefficient. -- -- For example using the Stream instance, a producer defined using -- this capability can be consumed efficiently in a streaming fashion. module Capability.Sink -- | Sinking capability. -- -- An instance does not need to fulfill any additional laws besides the -- monad laws. class Monad m => HasSink (tag :: k) (a :: Type) (m :: Type -> Type) | tag m -> a -- | For technical reasons, this method needs an extra proxy argument. You -- only need it if you are defining new instances of HasSink. -- Otherwise, you will want to use yield. See yield for -- more documentation. yield_ :: HasSink tag a m => Proxy# tag -> a -> m () -- | yield @tag a emits a in the sink capability -- tag. yield :: forall tag a m. HasSink tag a m => a -> m () -- | Type synonym using the TypeOf type family to specify -- HasSink constraints without having to specify the type -- associated to a tag. type HasSink' (tag :: k) = HasSink tag (TypeOf k tag) -- | Type family associating a tag to the corresponding type. It is -- intended to simplify constraint declarations, by removing the need to -- redundantly specify the type associated to a tag. -- -- It is poly-kinded, which allows users to define their own kind of -- tags. Standard haskell types can also be used as tags by specifying -- the Type kind when defining the type family instance. -- -- Defining TypeOf instances for Symbols (typelevel string -- literals) is discouraged. Since symbols all belong to the same global -- namespace, such instances could conflict with others defined in -- external libraries. More generally, as for typeclasses, TypeOf -- instances should always be defined in the same module as the tag type -- to prevent issues due to orphan instances. -- -- Example: -- --
-- import Capability.Reader -- -- data Foo -- data Bar -- type instance TypeOf Type Foo = Int -- type instance TypeOf Type Bar = String -- -- -- Same as: foo :: HasReader Foo Int M => … -- foo :: HasReader' Foo m => … -- foo = … --type family TypeOf k (s :: k) :: Type -- | Accumulate sunk values in a reverse order list. newtype SinkStack m (a :: Type) SinkStack :: m a -> SinkStack m (a :: Type) -- | Accumulate sunk values in forward order in a difference list. newtype SinkDList m (a :: Type) SinkDList :: m a -> SinkDList m (a :: Type) -- | Accumulate sunk values with their own monoid. newtype SinkLog m (a :: Type) SinkLog :: m a -> SinkLog m (a :: Type) -- | Deprecated: Use Sink module Capability.Stream type HasStream = HasSink type HasStream' tag = HasSink' tag -- | yield @tag a emits a in the sink capability -- tag. yield :: forall tag a m. HasSink tag a m => a -> m () type StreamStack = SinkStack type StreamDList = SinkDList type StreamLog = SinkLog -- | Defines a capability type class for a reader effect. A reader provides -- an environment, say an initialization context or a configuration. The -- environment held in the reader effect can be changed (with -- local) within the scope of a sub-computation. Contrary to the -- Capability.State, such a change is local, and does not persist -- when the local call ends. module Capability.Reader -- | Reader capability -- -- An instance should fulfill the following laws. At this point these -- laws are not definitive, see -- https://github.com/haskell/mtl/issues/5. -- --
-- k <*> ask @t = ask @t <**> k ---- --
-- ask @t *> m = m = m <* ask @t ---- --
-- local @t f (ask @t) = fmap f (ask @t) ---- --
-- local @t f . local @t g = local @t (g . f) ---- --
-- local @t f (pure x) = pure x ---- --
-- local @t f (m >>= \x -> k x) = local @t f m >>= \x -> local @t f (k x) ---- --
-- reader @t f = f <$> ask @t --class (Monad m, HasSource tag r m) => HasReader (tag :: k) (r :: Type) (m :: Type -> Type) | tag m -> r -- | For technical reasons, this method needs an extra proxy argument. You -- only need it if you are defining new instances of HasReader. -- Otherwise, you will want to use local. See local for -- more documentation. local_ :: HasReader tag r m => Proxy# tag -> (r -> r) -> m a -> m a -- | For technical reasons, this method needs an extra proxy argument. You -- only need it if you are defining new instances of HasReader. -- Otherwise, you will want to use reader. See reader for -- more documentation. reader_ :: HasReader tag r m => Proxy# tag -> (r -> a) -> m a -- | ask @tag retrieves the environment of the reader capability -- tag. ask :: forall tag r m. HasReader tag r m => m r -- | asks @tag retrieves the image by f of the -- environment of the reader capability tag. -- --
-- asks @tag f = f <$> ask @tag --asks :: forall tag r m a. HasReader tag r m => (r -> a) -> m a -- | local @tag f m runs the monadic action m in a -- modified environment e' = f e, where e is the -- environment of the reader capability tag. Symbolically: -- return e = ask @tag. local :: forall tag r m a. HasReader tag r m => (r -> r) -> m a -> m a -- | reader @tag act lifts a purely environment-dependent action -- act to a monadic action in an arbitrary monad m with -- capability HasReader. -- -- It happens to coincide with asks: reader = asks. reader :: forall tag r m a. HasReader tag r m => (r -> a) -> m a -- | Execute the given reader action on a sub-component of the current -- context as defined by the given transformer t, retaining -- arbitrary capabilities listed in cs. -- -- See the similar zoom function for more details and examples. -- -- This function is experimental and subject to change. See -- https://github.com/tweag/capability/issues/46. magnify :: forall innertag t (cs :: [Capability]) inner m a. (forall x. Coercible (t m x) (m x), HasReader innertag inner (t m), All cs m) => (forall m'. All (HasReader innertag inner : cs) m' => m' a) -> m a -- |
-- Reified tag capability m ---- -- Defines the dictionary type for the methods of capability -- under tag in the monad m. Refer to interpret_ -- for an example use-case. -- -- For example, the HasSink capability has the method -- yield :: a -> m (). The corresponding dictionary -- type is defined as follows. -- --
-- >>> :{
-- data instance Reified tag (HasSink tag a) m =
-- ReifiedSink { _yield :: forall a. a -> m () }
-- :}
--
--
-- Superclass dictionaries are represented as nested records. For
-- example, the HasState capability has the superclasses
-- HasSource and HasSink and the method state ::
-- (s -> (a, s)) -> m a. The corresponding dictionary type is
-- defined as follows.
--
--
-- >>> :{
-- data instance Reified tag (HasState tag s) m =
-- ReifiedState
-- { _stateSource :: Reified tag (HasSource tag s) m,
-- _stateSink :: Reified tag (HasSink tag s) m,
-- _state :: forall a. (s -> (a, s)) -> m a
-- }
-- :}
--
data family Reified (tag :: k) (c :: Capability) (m :: Type -> Type)
-- | Type synonym using the TypeOf type family to specify
-- HasReader constraints without having to specify the type
-- associated to a tag.
type HasReader' (tag :: k) = HasReader tag (TypeOf k tag)
-- | Type family associating a tag to the corresponding type. It is
-- intended to simplify constraint declarations, by removing the need to
-- redundantly specify the type associated to a tag.
--
-- It is poly-kinded, which allows users to define their own kind of
-- tags. Standard haskell types can also be used as tags by specifying
-- the Type kind when defining the type family instance.
--
-- Defining TypeOf instances for Symbols (typelevel string
-- literals) is discouraged. Since symbols all belong to the same global
-- namespace, such instances could conflict with others defined in
-- external libraries. More generally, as for typeclasses, TypeOf
-- instances should always be defined in the same module as the tag type
-- to prevent issues due to orphan instances.
--
-- Example:
--
-- -- import Capability.Reader -- -- data Foo -- data Bar -- type instance TypeOf Type Foo = Int -- type instance TypeOf Type Bar = String -- -- -- Same as: foo :: HasReader Foo Int M => … -- foo :: HasReader' Foo m => … -- foo = … --type family TypeOf k (s :: k) :: Type -- | Derive HasSource from m's MonadReader instance. newtype MonadReader (m :: Type -> Type) (a :: Type) MonadReader :: m a -> MonadReader (m :: Type -> Type) (a :: Type) -- | Convert a pure state monad into a reader monad. -- -- Pure meaning that the monad stack does not allow catching -- exceptions. Otherwise, an exception occurring in the action passed to -- local could cause the context to remain modified outside of -- the call to local. E.g. -- --
-- local @tag (const r') (throw MyException) -- `catch` \MyException -> ask @tag ---- -- returns r' instead of the previous value. -- -- Note, that no MonadIO instance is provided, as this would -- allow catching exceptions. -- -- See ReadState. newtype ReadStatePure (m :: Type -> Type) (a :: Type) ReadStatePure :: m a -> ReadStatePure (m :: Type -> Type) (a :: Type) -- | Convert a state monad into a reader monad. -- -- Use this if the monad stack allows catching exceptions. -- -- See ReadStatePure. newtype ReadState (m :: Type -> Type) (a :: Type) ReadState :: m a -> ReadState (m :: Type -> Type) (a :: Type) -- | Defines capabilities for actions that may fail or throw exceptions, -- and optionally may catch exceptions. -- -- Monads based on IO can use the underlying IO -- exception mechanism to that end. The details of synchronous and -- asynchronous exception handling depend on the strategy used. See -- MonadThrow, SafeExceptions, MonadUnliftIO. -- -- The associated tag can be used to select the exception type, or to -- select a layer in monad transformer stacks. Note, that it is illegal -- to have multiple tags refer to overlapping exception types in the same -- layer. Consider the following example -- --
-- newtype M a = M (IO a) -- deriving (HasThrow "foo" IOException) via -- MonadUnliftIO IO -- deriving (HasThrow "bar" SomeException) via -- MonadUnliftIO IO ---- -- In this case the tags "foo" and "bar" refer to -- overlapping exception types in the same layer, because catch -- @"bar" may also catch an exception thrown under "foo". module Capability.Error -- | Capability to throw exceptions of type e under tag. -- -- HasThrow/HasCatch capabilities at different tags -- should be independent. See HasCatch. class Monad m => HasThrow (tag :: k) (e :: Type) (m :: Type -> Type) | tag m -> e -- | For technical reasons, this method needs an extra proxy argument. You -- only need it if you are defining new instances of HasReader. -- Otherwise, you will want to use throw. See throw for -- more documentation. throw_ :: HasThrow tag e m => Proxy# tag -> e -> m a -- | Throw an exception in the specified exception capability. throw :: forall tag e m a. HasThrow tag e m => e -> m a -- | Capability to catch exceptions of type e under tag. -- -- HasThrow/HasCatch capabilities at different tags -- should be independent. In particular, the following program should -- throw SomeError and not return (). > example :: -- > (HasThrow Left SomeError m, HasCatch Right -- SomeError m) > => m () > example = > catch Left -- > (throw Right SomeError) > _ -> pure () -- -- See wrapError for a way to combine multiple exception types -- into one. class HasThrow tag e m => HasCatch (tag :: k) (e :: Type) (m :: Type -> Type) | tag m -> e -- | For technical reasons, this method needs an extra proxy argument. You -- only need it if you are defining new instances of HasReader. -- Otherwise, you will want to use catch. See catch for -- more documentation. catch_ :: HasCatch tag e m => Proxy# tag -> m a -> (e -> m a) -> m a -- | For technical reasons, this method needs an extra proxy argument. You -- only need it if you are defining new instances of HasReader. -- Otherwise, you will want to use catchJust. See catchJust -- for more documentation. catchJust_ :: HasCatch tag e m => Proxy# tag -> (e -> Maybe b) -> m a -> (b -> m a) -> m a -- | Provide a handler for exceptions thrown in the given action in the -- given exception capability. catch :: forall tag e m a. HasCatch tag e m => m a -> (e -> m a) -> m a -- | Like catch, but only handle the exception if the provided -- function returns Just. catchJust :: forall tag e m a b. HasCatch tag e m => (e -> Maybe b) -> m a -> (b -> m a) -> m a -- | Wrap exceptions inner originating from the given action -- according to the accessor t. Retain arbitrary capabilities -- listed in cs. -- -- Example: -- --
-- wrapError -- @"ComponentError" @(Ctor "ComponentError" "AppError") @'[] -- component -- -- component :: HasError "ComponentError" ComponentError m => m () -- data AppError = ComponentError ComponentError ---- -- This function is experimental and subject to change. See -- https://github.com/tweag/capability/issues/46. wrapError :: forall innertag t (cs :: [Capability]) inner m a. (forall x. Coercible (t m x) (m x), HasCatch innertag inner (t m), All cs m) => (forall m'. All (HasCatch innertag inner : cs) m' => m' a) -> m a -- | Type synonym using the TypeOf type family to specify -- HasThrow constraints without having to specify the type -- associated to a tag. type HasThrow' (tag :: k) = HasThrow tag (TypeOf k tag) -- | Type synonym using the TypeOf type family to specify -- HasCatch constraints without having to specify the type -- associated to a tag. type HasCatch' (tag :: k) = HasCatch tag (TypeOf k tag) -- | Type family associating a tag to the corresponding type. It is -- intended to simplify constraint declarations, by removing the need to -- redundantly specify the type associated to a tag. -- -- It is poly-kinded, which allows users to define their own kind of -- tags. Standard haskell types can also be used as tags by specifying -- the Type kind when defining the type family instance. -- -- Defining TypeOf instances for Symbols (typelevel string -- literals) is discouraged. Since symbols all belong to the same global -- namespace, such instances could conflict with others defined in -- external libraries. More generally, as for typeclasses, TypeOf -- instances should always be defined in the same module as the tag type -- to prevent issues due to orphan instances. -- -- Example: -- --
-- import Capability.Reader -- -- data Foo -- data Bar -- type instance TypeOf Type Foo = Int -- type instance TypeOf Type Bar = String -- -- -- Same as: foo :: HasReader Foo Int M => … -- foo :: HasReader' Foo m => … -- foo = … --type family TypeOf k (s :: k) :: Type -- | Derive 'HasError from m's MonadError instance. newtype MonadError m (a :: Type) MonadError :: m a -> MonadError m (a :: Type) -- | Derive HasThrow from m's MonadThrow instance. newtype MonadThrow (e :: Type) m (a :: Type) MonadThrow :: m a -> MonadThrow (e :: Type) m (a :: Type) -- | Derive 'HasCatch from m's 'Control.Monad.Catch.MonadCatch -- instance. newtype MonadCatch (e :: Type) m (a :: Type) MonadCatch :: m a -> MonadCatch (e :: Type) m (a :: Type) -- | Derive HasError using the functionality from the -- safe-exceptions package. newtype SafeExceptions (e :: Type) m (a :: Type) SafeExceptions :: m a -> SafeExceptions (e :: Type) m (a :: Type) -- | Derive HasError using the functionality from the -- unliftio package. newtype MonadUnliftIO (e :: Type) m (a :: Type) MonadUnliftIO :: m a -> MonadUnliftIO (e :: Type) m (a :: Type) -- |
-- Reified tag capability m ---- -- Defines the dictionary type for the methods of capability -- under tag in the monad m. Refer to interpret_ -- for an example use-case. -- -- For example, the HasSink capability has the method -- yield :: a -> m (). The corresponding dictionary -- type is defined as follows. -- --
-- >>> :{
-- data instance Reified tag (HasSink tag a) m =
-- ReifiedSink { _yield :: forall a. a -> m () }
-- :}
--
--
-- Superclass dictionaries are represented as nested records. For
-- example, the HasState capability has the superclasses
-- HasSource and HasSink and the method state ::
-- (s -> (a, s)) -> m a. The corresponding dictionary type is
-- defined as follows.
--
--
-- >>> :{
-- data instance Reified tag (HasState tag s) m =
-- ReifiedState
-- { _stateSource :: Reified tag (HasSource tag s) m,
-- _stateSink :: Reified tag (HasSink tag s) m,
-- _state :: forall a. (s -> (a, s)) -> m a
-- }
-- :}
--
data family Reified (tag :: k) (c :: Capability) (m :: Type -> Type)
-- | 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
-- | The class Typeable allows a concrete representation of a type
-- to be calculated.
class Typeable (a :: k)
instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Capability.Error.MonadError m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Capability.Error.MonadError m)
instance GHC.Base.Monad m => GHC.Base.Monad (Capability.Error.MonadError m)
instance GHC.Base.Applicative m => GHC.Base.Applicative (Capability.Error.MonadError m)
instance GHC.Base.Functor m => GHC.Base.Functor (Capability.Error.MonadError m)
instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Capability.Error.MonadThrow e m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Capability.Error.MonadThrow e m)
instance GHC.Base.Monad m => GHC.Base.Monad (Capability.Error.MonadThrow e m)
instance GHC.Base.Applicative m => GHC.Base.Applicative (Capability.Error.MonadThrow e m)
instance GHC.Base.Functor m => GHC.Base.Functor (Capability.Error.MonadThrow e m)
instance forall k (tag :: k) e (m :: * -> *). (GHC.Exception.Type.Exception e, Control.Monad.Catch.MonadThrow m) => Capability.Error.HasThrow tag e (Capability.Error.MonadCatch e m)
instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Capability.Error.MonadCatch e m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Capability.Error.MonadCatch e m)
instance GHC.Base.Monad m => GHC.Base.Monad (Capability.Error.MonadCatch e m)
instance GHC.Base.Applicative m => GHC.Base.Applicative (Capability.Error.MonadCatch e m)
instance GHC.Base.Functor m => GHC.Base.Functor (Capability.Error.MonadCatch e m)
instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Capability.Error.SafeExceptions e m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Capability.Error.SafeExceptions e m)
instance GHC.Base.Monad m => GHC.Base.Monad (Capability.Error.SafeExceptions e m)
instance GHC.Base.Applicative m => GHC.Base.Applicative (Capability.Error.SafeExceptions e m)
instance GHC.Base.Functor m => GHC.Base.Functor (Capability.Error.SafeExceptions e m)
instance Control.Monad.Primitive.PrimMonad m => Control.Monad.Primitive.PrimMonad (Capability.Error.MonadUnliftIO e m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Capability.Error.MonadUnliftIO e m)
instance GHC.Base.Monad m => GHC.Base.Monad (Capability.Error.MonadUnliftIO e m)
instance GHC.Base.Applicative m => GHC.Base.Applicative (Capability.Error.MonadUnliftIO e m)
instance GHC.Base.Functor m => GHC.Base.Functor (Capability.Error.MonadUnliftIO e m)
instance forall k (tag :: k) e (t2 :: (* -> *) -> * -> *) (t1 :: (* -> *) -> * -> *) (m :: * -> *). (forall x. GHC.Types.Coercible (m x) (t2 (t1 m) x), GHC.Base.Monad m, Capability.Error.HasThrow tag e (t2 (t1 m))) => Capability.Error.HasThrow tag e ((Capability.Accessors.:.:) t2 t1 m)
instance forall k (tag :: k) e (t2 :: (* -> *) -> * -> *) (t1 :: (* -> *) -> * -> *) (m :: * -> *). (forall x. GHC.Types.Coercible (m x) (t2 (t1 m) x), GHC.Base.Monad m, Capability.Error.HasCatch tag e (t2 (t1 m))) => Capability.Error.HasCatch tag e ((Capability.Accessors.:.:) t2 t1 m)
instance forall k e (m :: * -> *) (tag :: k). (GHC.Exception.Type.Exception e, Control.Monad.IO.Class.MonadIO m) => Capability.Error.HasThrow tag e (Capability.Error.MonadUnliftIO e m)
instance forall k e (m :: * -> *) (tag :: k). (GHC.Exception.Type.Exception e, Control.Monad.IO.Unlift.MonadUnliftIO m) => Capability.Error.HasCatch tag e (Capability.Error.MonadUnliftIO e m)
instance forall k e (m :: * -> *) (tag :: k). (GHC.Exception.Type.Exception e, Control.Monad.Catch.MonadThrow m) => Capability.Error.HasThrow tag e (Capability.Error.SafeExceptions e m)
instance forall k e (m :: * -> *) (tag :: k). (GHC.Exception.Type.Exception e, Control.Monad.Catch.MonadCatch m) => Capability.Error.HasCatch tag e (Capability.Error.SafeExceptions e m)
instance forall k e (m :: * -> *) (tag :: k). (GHC.Exception.Type.Exception e, Control.Monad.Catch.MonadCatch m) => Capability.Error.HasCatch tag e (Capability.Error.MonadCatch e m)
instance forall k e (m :: * -> *) (tag :: k). (GHC.Exception.Type.Exception e, Control.Monad.Catch.MonadThrow m) => Capability.Error.HasThrow tag e (Capability.Error.MonadThrow e m)
instance forall k e (m :: * -> *) (tag :: k). Control.Monad.Error.Class.MonadError e m => Capability.Error.HasThrow tag e (Capability.Error.MonadError m)
instance forall k e (m :: * -> *) (tag :: k). Control.Monad.Error.Class.MonadError e m => Capability.Error.HasCatch tag e (Capability.Error.MonadError m)
instance forall k1 k2 (oldtag :: k1) e (m :: * -> *) (newtag :: k2). Capability.Error.HasCatch oldtag e m => Capability.Error.HasCatch newtag e (Capability.Accessors.Rename oldtag m)
instance forall k (ctor :: GHC.Types.Symbol) sum e (oldtag :: k) (m :: * -> *). (Data.Generics.Sum.Constructors.AsConstructor' ctor sum e, Capability.Error.HasCatch oldtag sum m) => Capability.Error.HasCatch ctor e (Capability.Accessors.Ctor ctor oldtag m)
instance forall k (tag :: k) e (m :: * -> *) (t :: (* -> *) -> * -> *). (Capability.Error.HasCatch tag e m, Control.Monad.Trans.Control.MonadTransControl t, GHC.Base.Monad (t m)) => Capability.Error.HasCatch tag e (Capability.Accessors.Lift (t m))
instance forall k (m :: * -> *) s (tag :: k) e. (GHC.Base.Monad m, Data.Reflection.Reifies s (Capability.Reflection.Reified tag (Capability.Error.HasCatch tag e) m)) => Capability.Error.HasThrow tag e (Capability.Reflection.Reflected s (Capability.Error.HasCatch tag e) m)
instance forall k (m :: * -> *) s (tag :: k) e. (GHC.Base.Monad m, Data.Reflection.Reifies s (Capability.Reflection.Reified tag (Capability.Error.HasCatch tag e) m)) => Capability.Error.HasCatch tag e (Capability.Reflection.Reflected s (Capability.Error.HasCatch tag e) m)
instance forall k1 k2 (oldtag :: k1) e (m :: * -> *) (newtag :: k2). Capability.Error.HasThrow oldtag e m => Capability.Error.HasThrow newtag e (Capability.Accessors.Rename oldtag m)
instance forall k (ctor :: GHC.Types.Symbol) sum e (oldtag :: k) (m :: * -> *). (Data.Generics.Sum.Constructors.AsConstructor' ctor sum e, Capability.Error.HasThrow oldtag sum m) => Capability.Error.HasThrow ctor e (Capability.Accessors.Ctor ctor oldtag m)
instance forall k (tag :: k) e (m :: * -> *) (t :: (* -> *) -> * -> *). (Capability.Error.HasThrow tag e m, Control.Monad.Trans.Class.MonadTrans t, GHC.Base.Monad (t m)) => Capability.Error.HasThrow tag e (Capability.Accessors.Lift (t m))
instance forall k (m :: * -> *) s (tag :: k) e. (GHC.Base.Monad m, Data.Reflection.Reifies s (Capability.Reflection.Reified tag (Capability.Error.HasThrow tag e) m)) => Capability.Error.HasThrow tag e (Capability.Reflection.Reflected s (Capability.Error.HasThrow tag e) m)
-- | Defines a capability type class for writer effects. A writer program
-- can output values with tell. The values output by two
-- consecutive sub-computation are combined using a monoid's
-- mappend.
--
-- The interface of HasWriter follows that of MonadWriter.
-- However, this module does not include a strategy to provide a
-- HasWriter capability from a MonadWriter instance. It
-- is generally a bad idea to use monads such as WriterT, as they
-- tend to leak space, as described in this
-- <https://blog.infinitenegativeutility.com/2016/7/writer-monads-and-space-leaks
-- blog post> by Getty Ritter.
--
-- Instead, you should use the WriterLog strategy that implements
-- the writer monad on a state monad. There is no downside, as using
-- HasWriter instead of HasState directly ensures your code
-- adheres to the writer monad interface and does not misuse the
-- underlying state monad.
module Capability.Writer
-- | Writer capability
--
-- An instance should fulfill the following laws. At this point these
-- laws are not definitive, see
-- https://github.com/haskell/mtl/issues/5.
--
-- -- listen @t (pure a) = pure (a, mempty) ---- --
-- listen @t (tell @t w) = tell @t w >> pure (w, w) ---- --
-- listen @t (m >>= k) = listen @t m >>= \(a, w1) -> listen @t (k a) >>= \(b, w2) -> pure (b, w1 `mappend` w2) ---- --
-- pass @t (tell @t w >> pure (a, f)) = tell @t (f w) >> pure a ---- --
-- writer @t (a, w) = tell @t w >> pure a ---- --
-- import Capability.Reader -- -- data Foo -- data Bar -- type instance TypeOf Type Foo = Int -- type instance TypeOf Type Bar = String -- -- -- Same as: foo :: HasReader Foo Int M => … -- foo :: HasReader' Foo m => … -- foo = … --type family TypeOf k (s :: k) :: Type type WriterLog = SinkLog type StreamLog = SinkLog -- | Accumulate sunk values with their own monoid. newtype SinkLog m (a :: Type) SinkLog :: m a -> SinkLog m (a :: Type) -- |
-- Reified tag capability m ---- -- Defines the dictionary type for the methods of capability -- under tag in the monad m. Refer to interpret_ -- for an example use-case. -- -- For example, the HasSink capability has the method -- yield :: a -> m (). The corresponding dictionary -- type is defined as follows. -- --
-- >>> :{
-- data instance Reified tag (HasSink tag a) m =
-- ReifiedSink { _yield :: forall a. a -> m () }
-- :}
--
--
-- Superclass dictionaries are represented as nested records. For
-- example, the HasState capability has the superclasses
-- HasSource and HasSink and the method state ::
-- (s -> (a, s)) -> m a. The corresponding dictionary type is
-- defined as follows.
--
--
-- >>> :{
-- data instance Reified tag (HasState tag s) m =
-- ReifiedState
-- { _stateSource :: Reified tag (HasSource tag s) m,
-- _stateSink :: Reified tag (HasSink tag s) m,
-- _state :: forall a. (s -> (a, s)) -> m a
-- }
-- :}
--
data family Reified (tag :: k) (c :: Capability) (m :: Type -> Type)
instance forall k (tag :: k) w (t2 :: (* -> *) -> * -> *) (t1 :: (* -> *) -> * -> *) (m :: * -> *). (forall x. GHC.Types.Coercible (m x) (t2 (t1 m) x), GHC.Base.Monad m, Capability.Writer.HasWriter tag w (t2 (t1 m))) => Capability.Writer.HasWriter tag w ((Capability.Accessors.:.:) t2 t1 m)
instance forall k w (tag :: k) (m :: * -> *). (GHC.Base.Monoid w, Capability.State.Internal.Class.HasState tag w m) => Capability.Writer.HasWriter tag w (Capability.Writer.WriterLog m)
instance forall k w (m :: * -> *) s (tag :: k). (GHC.Base.Monoid w, GHC.Base.Monad m, Data.Reflection.Reifies s (Capability.Reflection.Reified tag (Capability.Writer.HasWriter tag w) m)) => Capability.Sink.Internal.Class.HasSink tag w (Capability.Reflection.Reflected s (Capability.Writer.HasWriter tag w) m)
instance forall k (m :: * -> *) w s (tag :: k). (GHC.Base.Monad m, GHC.Base.Monoid w, Data.Reflection.Reifies s (Capability.Reflection.Reified tag (Capability.Writer.HasWriter tag w) m)) => Capability.Writer.HasWriter tag w (Capability.Reflection.Reflected s (Capability.Writer.HasWriter tag w) m)