capability-0.5.0.0: Extensional capabilities and deriving combinators
Safe HaskellNone
LanguageHaskell2010

Capability.State

Description

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

Relational capability

class (Monad m, HasSource tag s m, HasSink tag s m) => HasState (tag :: k) (s :: Type) (m :: Type -> Type) | 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

Methods

state_ :: Proxy# tag -> (s -> (a, s)) -> m a 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 state. See state for more documentation.

Instances

Instances details
(MutableRef ref, RefElement ref ~ s, HasReader tag ref m, PrimMonad m, PrimState m ~ MCState ref) => HasState (tag :: k) s (ReaderRef m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies

Methods

state_ :: Proxy# tag -> (s -> (a, s)) -> ReaderRef m a 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.

Instance details

Defined in Capability.State.Internal.Strategies

Methods

state_ :: Proxy# tag -> (s -> (a, s)) -> Lift (t m) a Source #

MonadState s m => HasState (tag :: k) s (MonadState m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies

Methods

state_ :: Proxy# tag -> (s -> (a, s)) -> MonadState m a Source #

(HasReader tag (IORef s) m, MonadIO m) => HasState (tag :: k) s (ReaderIORef m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies

Methods

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.

Instance details

Defined in Capability.State.Internal.Strategies

Methods

state_ :: Proxy# tag -> (to -> (a, to)) -> Coerce to m a Source #

(Monad m, Reifies s' (Reified tag (HasState tag s) m)) => HasSink (tag :: k) s (Reflected s' (HasState tag s) m) Source # 
Instance details

Defined in Capability.State.Internal.Class

Methods

yield_ :: Proxy# tag -> s -> Reflected s' (HasState tag s) m () Source #

(Monad m, Reifies s' (Reified tag (HasState tag s) m)) => HasSource (tag :: k) s (Reflected s' (HasState tag s) m) Source # 
Instance details

Defined in Capability.State.Internal.Class

Methods

await_ :: Proxy# tag -> Reflected s' (HasState tag s) m s Source #

(Monad m, Reifies s' (Reified tag (HasState tag s) m)) => HasState (tag :: k) s (Reflected s' (HasState tag s) m) Source # 
Instance details

Defined in Capability.State.Internal.Class

Methods

state_ :: Proxy# tag -> (s -> (a, s)) -> Reflected s' (HasState tag s) m a Source #

HasState oldtag s m => HasState (newtag :: k2) s (Rename oldtag m) Source #

Rename the tag.

Instance details

Defined in Capability.State.Internal.Strategies

Methods

state_ :: Proxy# newtag -> (s -> (a, s)) -> Rename oldtag m a Source #

(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.

Instance details

Defined in Capability.State.Internal.Strategies

Methods

state_ :: Proxy# tag -> (s -> (a, s)) -> (t2 :.: t1) m a Source #

(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 pos of type v in the state struct.

Instance details

Defined in Capability.State.Internal.Strategies

Methods

state_ :: Proxy# tag -> (v -> (a, v)) -> Pos pos oldtag m a Source #

(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 field of type v in the state record.

Instance details

Defined in Capability.State.Internal.Strategies

Methods

state_ :: Proxy# tag -> (v -> (a, v)) -> Field field oldtag m a Source #

data Reified (tag :: k) (HasState tag s) m Source # 
Instance details

Defined in Capability.State.Internal.Class

data Reified (tag :: k) (HasState tag s) m = ReifiedState {}

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.

data family Reified (tag :: k) (c :: Capability) (m :: Type -> Type) Source #

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
      }
  :}

Instances

Instances details
data Reified (tag :: k) (HasSink tag a) m Source # 
Instance details

Defined in Capability.Sink.Internal.Class

data Reified (tag :: k) (HasSink tag a) m = ReifiedSink {}
data Reified (tag :: k) (HasSource tag a) m Source # 
Instance details

Defined in Capability.Source.Internal.Class

data Reified (tag :: k) (HasSource tag a) m = ReifiedSource {}
data Reified (tag :: k) (HasReader tag r) m Source # 
Instance details

Defined in Capability.Reader.Internal.Class

data Reified (tag :: k) (HasReader tag r) m = ReifiedReader {}
data Reified (tag :: k) (HasState tag s) m Source # 
Instance details

Defined in Capability.State.Internal.Class

data Reified (tag :: k) (HasState tag s) m = ReifiedState {}
data Reified (tag :: k) (HasThrow tag e) m Source # 
Instance details

Defined in Capability.Error

data Reified (tag :: k) (HasThrow tag e) m = ReifiedThrow {}
data Reified (tag :: k) (HasCatch tag e) m Source # 
Instance details

Defined in Capability.Error

data Reified (tag :: k) (HasCatch tag e) m = ReifiedCatch {}
data Reified (tag :: k) (HasWriter tag w) m Source # 
Instance details

Defined in Capability.Writer

data Reified (tag :: k) (HasWriter tag w) m = ReifiedWriter {}

Functional capability

type HasState' (tag :: k) = HasState tag (TypeOf k tag) Source #

Type synonym using the TypeOf type family to specify HasState constraints without having to specify the type associated to a tag.

type family TypeOf k (s :: k) :: Type 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 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 = …

Strategies

newtype MonadState (m :: Type -> Type) (a :: Type) Source #

Derive HasState from m's MonadState instance.

Constructors

MonadState (m a) 

Instances

Instances details
MonadState s m => HasSink (tag :: k) s (MonadState m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> s -> MonadState m () Source #

MonadState s m => HasSource (tag :: k) s (MonadState m) Source # 
Instance details

Defined in Capability.Source.Internal.Strategies

Methods

await_ :: Proxy# tag -> MonadState m s Source #

MonadState s m => HasState (tag :: k) s (MonadState m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies

Methods

state_ :: Proxy# tag -> (s -> (a, s)) -> MonadState m a Source #

Monad m => Monad (MonadState m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Methods

(>>=) :: MonadState m a -> (a -> MonadState m b) -> MonadState m b #

(>>) :: MonadState m a -> MonadState m b -> MonadState m b #

return :: a -> MonadState m a #

Functor m => Functor (MonadState m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Methods

fmap :: (a -> b) -> MonadState m a -> MonadState m b #

(<$) :: a -> MonadState m b -> MonadState m a #

Applicative m => Applicative (MonadState m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Methods

pure :: a -> MonadState m a #

(<*>) :: MonadState m (a -> b) -> MonadState m a -> MonadState m b #

liftA2 :: (a -> b -> c) -> MonadState m a -> MonadState m b -> MonadState m c #

(*>) :: MonadState m a -> MonadState m b -> MonadState m b #

(<*) :: MonadState m a -> MonadState m b -> MonadState m a #

MonadIO m => MonadIO (MonadState m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Methods

liftIO :: IO a -> MonadState m a #

PrimMonad m => PrimMonad (MonadState m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Associated Types

type PrimState (MonadState m) #

Methods

primitive :: (State# (PrimState (MonadState m)) -> (# State# (PrimState (MonadState m)), a #)) -> MonadState m a #

type PrimState (MonadState m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

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.

Constructors

ReaderIORef (m a) 

Instances

Instances details
(HasSource tag (IORef s) m, MonadIO m) => HasSink (tag :: k) s (ReaderIORef m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> s -> ReaderIORef m () Source #

(HasSource tag (IORef s) m, MonadIO m) => HasSource (tag :: k) s (ReaderIORef m) Source # 
Instance details

Defined in Capability.Source.Internal.Strategies

Methods

await_ :: Proxy# tag -> ReaderIORef m s Source #

(HasReader tag (IORef s) m, MonadIO m) => HasState (tag :: k) s (ReaderIORef m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies

Methods

state_ :: Proxy# tag -> (s -> (a, s)) -> ReaderIORef m a Source #

Monad m => Monad (ReaderIORef m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Methods

(>>=) :: ReaderIORef m a -> (a -> ReaderIORef m b) -> ReaderIORef m b #

(>>) :: ReaderIORef m a -> ReaderIORef m b -> ReaderIORef m b #

return :: a -> ReaderIORef m a #

Functor m => Functor (ReaderIORef m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Methods

fmap :: (a -> b) -> ReaderIORef m a -> ReaderIORef m b #

(<$) :: a -> ReaderIORef m b -> ReaderIORef m a #

Applicative m => Applicative (ReaderIORef m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Methods

pure :: a -> ReaderIORef m a #

(<*>) :: ReaderIORef m (a -> b) -> ReaderIORef m a -> ReaderIORef m b #

liftA2 :: (a -> b -> c) -> ReaderIORef m a -> ReaderIORef m b -> ReaderIORef m c #

(*>) :: ReaderIORef m a -> ReaderIORef m b -> ReaderIORef m b #

(<*) :: ReaderIORef m a -> ReaderIORef m b -> ReaderIORef m a #

newtype ReaderRef m (a :: Type) 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.

Constructors

ReaderRef (m a) 

Instances

Instances details
(MutableRef ref, RefElement ref ~ s, HasSource tag ref m, PrimMonad m, PrimState m ~ MCState ref) => HasSink (tag :: k) s (ReaderRef m) Source # 
Instance details

Defined in Capability.Sink.Internal.Strategies

Methods

yield_ :: Proxy# tag -> 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 # 
Instance details

Defined in Capability.Source.Internal.Strategies

Methods

await_ :: Proxy# tag -> ReaderRef m s Source #

(MutableRef ref, RefElement ref ~ s, HasReader tag ref m, PrimMonad m, PrimState m ~ MCState ref) => HasState (tag :: k) s (ReaderRef m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies

Methods

state_ :: Proxy# tag -> (s -> (a, s)) -> ReaderRef m a Source #

Monad m => Monad (ReaderRef m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Methods

(>>=) :: ReaderRef m a -> (a -> ReaderRef m b) -> ReaderRef m b #

(>>) :: ReaderRef m a -> ReaderRef m b -> ReaderRef m b #

return :: a -> ReaderRef m a #

Functor m => Functor (ReaderRef m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Methods

fmap :: (a -> b) -> ReaderRef m a -> ReaderRef m b #

(<$) :: a -> ReaderRef m b -> ReaderRef m a #

Applicative m => Applicative (ReaderRef m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Methods

pure :: a -> ReaderRef m a #

(<*>) :: ReaderRef m (a -> b) -> ReaderRef m a -> ReaderRef m b #

liftA2 :: (a -> b -> c) -> ReaderRef m a -> ReaderRef m b -> ReaderRef m c #

(*>) :: ReaderRef m a -> ReaderRef m b -> ReaderRef m b #

(<*) :: ReaderRef m a -> ReaderRef m b -> ReaderRef m a #

MonadIO m => MonadIO (ReaderRef m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Methods

liftIO :: IO a -> ReaderRef m a #

PrimMonad m => PrimMonad (ReaderRef m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Associated Types

type PrimState (ReaderRef m) #

Methods

primitive :: (State# (PrimState (ReaderRef m)) -> (# State# (PrimState (ReaderRef m)), a #)) -> ReaderRef m a #

type PrimState (ReaderRef m) Source # 
Instance details

Defined in Capability.State.Internal.Strategies.Common

Modifiers