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 => 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 outertag innertag t outer inner m a. (forall x. Coercible (t m x) (m x), forall m'. HasState outertag outer m' => HasState innertag inner (t m'), HasState outertag outer m) => (forall m'. HasState innertag inner m' => m' a) -> m a
- newtype MonadState (m :: * -> *) (a :: *) = MonadState (m a)
- newtype ReaderIORef m a = ReaderIORef (m a)
- newtype ReaderRef m (a :: *) = ReaderRef (m a)
- module Capability.Accessors
Interface
class Monad 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
get_ :: Proxy# tag -> m s Source #
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 get
.
See get
for more documentation.
Instances
(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 get_ :: Proxy# tag -> MonadState m s Source # put_ :: Proxy# tag -> s -> MonadState m () Source # state_ :: Proxy# tag -> (s -> (a, s)) -> MonadState m a Source # | |
(MutableRef ref, RefElement ref ~ s, HasReader tag ref m, PrimMonad m, PrimState m ~ MCState ref) => HasState (tag :: k) s (ReaderRef m) 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. |
(HasReader tag (IORef s) m, MonadIO m) => HasState (tag :: k) s (ReaderIORef m) Source # | |
Defined in Capability.State.Internal.Strategies get_ :: Proxy# tag -> ReaderIORef m s Source # put_ :: Proxy# tag -> s -> ReaderIORef m () Source # state_ :: Proxy# tag -> (s -> (a, s)) -> ReaderIORef m a Source # | |
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 outertag innertag t outer inner m a. (forall x. Coercible (t m x) (m x), forall m'. HasState outertag outer m' => HasState innertag inner (t m'), HasState outertag outer m) => (forall m'. HasState innertag inner 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
.
Example:
zoom @"foobar" @"foo" @(Field "foo" "foobar") foo :: HasState "foobar" FooBar m => m () foo :: HasState "foo" Int m => m () data FooBar = FooBar { foo :: Int, bar :: String }
This function is experimental and subject to change. See https://github.com/tweag/capability/issues/46.
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, 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 | |
MonadIO m => MonadIO (ReaderRef m) Source # | |
Defined in Capability.State.Internal.Strategies | |
PrimMonad m => PrimMonad (ReaderRef m) Source # | |
type PrimState (ReaderRef m) Source # | |
Defined in Capability.State.Internal.Strategies |
Modifiers
module Capability.Accessors