Safe Haskell | None |
---|---|
Language | Haskell2010 |
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.
Synopsis
- class (Monad m, HasSource tag s m, HasSink tag s m) => HasState (tag :: k) (s :: *) (m :: * -> *) | tag m -> s where
- get :: forall tag s m. HasState tag s m => m s
- put :: forall tag s m. HasState tag s m => s -> m ()
- state :: forall tag s m a. HasState tag s m => (s -> (a, s)) -> m a
- modify :: forall tag s m. HasState tag s m => (s -> s) -> m ()
- modify' :: forall tag s m. HasState tag s m => (s -> s) -> m ()
- gets :: forall tag s m a. HasState tag s m => (s -> a) -> m a
- 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
- type HasState' (tag :: k) = HasState tag (TypeOf k tag)
- type family TypeOf k (s :: k) :: *
- newtype MonadState (m :: * -> *) (a :: *) = MonadState (m a)
- newtype ReaderIORef m a = ReaderIORef (m a)
- newtype ReaderRef m (a :: *) = ReaderRef (m a)
- module Capability.Accessors
Relational capability
class (Monad m, HasSource tag s m, HasSink tag s m) => HasState (tag :: k) (s :: *) (m :: * -> *) | tag m -> s where Source #
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
Instances
(MutableRef ref, RefElement ref ~ s, HasReader tag ref m, PrimMonad m, PrimState m ~ MCState ref) => HasState (tag :: k) s (ReaderRef m) Source # | |
(HasState tag s m, MonadTrans t, Monad (t m)) => HasState (tag :: k) s (Lift (t m)) Source # | Lift one layer in a monad transformer stack. |
MonadState s m => HasState (tag :: k) s (MonadState m) Source # | |
Defined in Capability.State.Internal.Strategies state_ :: Proxy# tag -> (s -> (a, s)) -> MonadState m a Source # | |
(HasReader tag (IORef s) m, MonadIO m) => HasState (tag :: k) s (ReaderIORef m) Source # | |
Defined in Capability.State.Internal.Strategies state_ :: Proxy# tag -> (s -> (a, s)) -> ReaderIORef m a Source # | |
(Coercible from to, HasState tag from m, forall x y. Coercible x y => Coercible (m x) (m y)) => HasState (tag :: k) to (Coerce to m) Source # | Convert the state using safe coercion. |
HasState oldtag s m => HasState (newtag :: k1) s (Rename oldtag m) Source # | Rename the tag. |
(forall x. Coercible (m x) (t2 (t1 m) x), Monad m, HasState tag s (t2 (t1 m))) => HasState (tag :: k) s ((t2 :.: t1) m) Source # | Compose two accessors. |
(tag ~ pos, HasPosition' pos struct v, HasState oldtag struct m) => HasState (tag :: Nat) v (Pos pos oldtag m) Source # | Zoom in on the field at position |
(tag ~ field, HasField' field record v, HasState oldtag record m) => HasState (tag :: Symbol) v (Field field oldtag m) Source # | Zoom in on the record field |
get :: forall tag s m. HasState tag s m => m s Source #
get @tag
retrieve the current state of the state capability tag
.
put :: forall tag s m. HasState tag s m => s -> m () Source #
put @tag s
replace the current state of the state capability tag
with s
.
state :: forall tag s m a. HasState tag s m => (s -> (a, s)) -> m a Source #
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
.
modify :: forall tag s m. HasState tag s m => (s -> s) -> m () Source #
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 () Source #
Same as modify
but strict in the new state.
gets :: forall tag s m a. HasState tag s m => (s -> a) -> m a Source #
gets @tag f
retrieves the image, by f
of the current state
of the state capability tag
.
gets @tag f = f <$> get @tag
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 Source #
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.
Functional capability
type family TypeOf k (s :: k) :: * Source #
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 *
kind
when defining the type family instance.
Defining TypeOf
instances for Symbol
s (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 * Foo = Int type instance TypeOf * Bar = String -- Same as: foo :: HasReader Foo Int M => … foo :: HasReader' Foo m => … foo = …
Strategies
newtype MonadState (m :: * -> *) (a :: *) Source #
Derive HasState
from m
's
MonadState
instance.
MonadState (m a) |
Instances
newtype ReaderIORef m a Source #
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.
ReaderIORef (m a) |
Instances
newtype ReaderRef m (a :: *) Source #
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
.
ReaderRef (m a) |
Instances
(MutableRef ref, RefElement ref ~ s, HasSource tag ref m, PrimMonad m, PrimState m ~ MCState ref) => HasSink (tag :: k) s (ReaderRef m) Source # | |
(MutableRef ref, RefElement ref ~ s, HasSource tag ref m, PrimMonad m, PrimState m ~ MCState ref) => HasSource (tag :: k) s (ReaderRef m) Source # | |
(MutableRef ref, RefElement ref ~ s, HasReader tag ref m, PrimMonad m, PrimState m ~ MCState ref) => HasState (tag :: k) s (ReaderRef m) Source # | |
Monad m => Monad (ReaderRef m) Source # | |
Functor m => Functor (ReaderRef m) Source # | |
Applicative m => Applicative (ReaderRef m) Source # | |
Defined in Capability.State.Internal.Strategies.Common | |
MonadIO m => MonadIO (ReaderRef m) Source # | |
Defined in Capability.State.Internal.Strategies.Common | |
PrimMonad m => PrimMonad (ReaderRef m) Source # | |
type PrimState (ReaderRef m) Source # | |
Defined in Capability.State.Internal.Strategies.Common |
Modifiers
module Capability.Accessors