covenant
Safe HaskellNone
LanguageHaskell2010

Control.Monad.Action

Description

Monoid actions, and the update monad, as well as an mtl-style capability type class.

A note on functional dependencies

To ensure easy inference, we make use of functional dependencies (either directly or by an equivalent mechanism on associated type families) on both the Action and MonadUpdate type classes. Specifically, we insist that:

  1. Any monoidal action determines the state it acts on; and
  2. Any particular stack that implements MonadUpdate determines what its action is.

This means that any given action can act on _exactly_ one state, and that any given stack has at most one state we can act upon. The second restriction above is in line with the other similar mtl-style capability type classes (such as MonadReader, MonadState etc), while the first is a reasonable choice given that we want to have both good inference and also the ability for different actions to act on the same state. Given that actions are likely to be fairly application-specific, we don't see this as a significant limitation.

Synopsis

Monoid actions

Class

class Monoid a => Action a where Source #

Describes (left) monoidal actions on a set. In this case, the type StateOf a is 'the state being acted on' (or 'the state'), while a is 'the thing doing the acting' (or 'the action').

Laws

Briefly, any instance of Action a defines a monoid homomorphism between a and Endo (StateOf a) (which is essentially StateOf a -> StateOf a). In Haskell terms, this means the following laws must hold:

  1. act mempty = mempty
  2. act x <> act y = act (x <> y)

Since: 1.0.0

Associated Types

type StateOf a Source #

Methods

act :: a -> Endo (StateOf a) Source #

Wrapper

data Actionable a Source #

Often, we want to take a type that doesn't (naturally) form a Monoid and use it as an action. This can be done using a range of 'free monoid constructions', including lists. However, these aren't optimal due to the append-heavy (and concatenation-heavy) workloads we typically need from actions.

Actionable is such a 'free monoid construction' which 'promotes' any a into a Semigroup and a Monoid. It is fairly opaque, providing only the instances we really need, but it's designed for efficient appending and concatenation.

To use Actionable, you want to do something like this:

data MyState = ...

data MyType = ...

newtype MyAction = MyAction (Actionable MyType)
 deriving (Semigroup, Monoid) via (Actionable MyType)

instance Action MyAction where
   type StateOf MyAction = MyState
   act (MyAction acts) = foldMap go acts
   where
     go :: MyType -> Endo MyState
     go x = Endo $ oldState -> ...

To 'inject' your type into an Actionable, use actionable.

Since: 1.0.0

Instances

Instances details
Foldable Actionable Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Methods

fold :: Monoid m => Actionable m -> m #

foldMap :: Monoid m => (a -> m) -> Actionable a -> m #

foldMap' :: Monoid m => (a -> m) -> Actionable a -> m #

foldr :: (a -> b -> b) -> b -> Actionable a -> b #

foldr' :: (a -> b -> b) -> b -> Actionable a -> b #

foldl :: (b -> a -> b) -> b -> Actionable a -> b #

foldl' :: (b -> a -> b) -> b -> Actionable a -> b #

foldr1 :: (a -> a -> a) -> Actionable a -> a #

foldl1 :: (a -> a -> a) -> Actionable a -> a #

toList :: Actionable a -> [a] #

null :: Actionable a -> Bool #

length :: Actionable a -> Int #

elem :: Eq a => a -> Actionable a -> Bool #

maximum :: Ord a => Actionable a -> a #

minimum :: Ord a => Actionable a -> a #

sum :: Num a => Actionable a -> a #

product :: Num a => Actionable a -> a #

Monoid (Actionable a) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Semigroup (Actionable a) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

actionable :: a -> Actionable a Source #

Wrap a value into an Actionable.

Since: 1.0.0

Action monad

Transformer

newtype UpdateT act (m :: Type -> Type) a Source #

A transformer implementing the 'update monad' pattern, as described here.

We leave the state implicit, as it is uniquely determined by the act type, together with the Action type class requirement.

Important note

This implementation is not suitable for any m that throws exceptions. This includes IO, ST and anything stacked atop them. For the reasons why, see here.

Since: 1.0.0

Constructors

UpdateT (StateOf act -> m (act, a)) 

Instances

Instances details
(Action act, Monad m) => MonadUpdate act (UpdateT act m) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Methods

send :: act -> UpdateT act m (StateOf act) Source #

update :: act -> UpdateT act m () Source #

request :: UpdateT act m (StateOf act) Source #

Action act => MonadTrans (UpdateT act) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Methods

lift :: Monad m => m a -> UpdateT act m a #

(Action act, Monad m) => Applicative (UpdateT act m) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Methods

pure :: a -> UpdateT act m a #

(<*>) :: UpdateT act m (a -> b) -> UpdateT act m a -> UpdateT act m b #

liftA2 :: (a -> b -> c) -> UpdateT act m a -> UpdateT act m b -> UpdateT act m c #

(*>) :: UpdateT act m a -> UpdateT act m b -> UpdateT act m b #

(<*) :: UpdateT act m a -> UpdateT act m b -> UpdateT act m a #

Functor m => Functor (UpdateT act m) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Methods

fmap :: (a -> b) -> UpdateT act m a -> UpdateT act m b #

(<$) :: a -> UpdateT act m b -> UpdateT act m a #

(Action act, Monad m) => Monad (UpdateT act m) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Methods

(>>=) :: UpdateT act m a -> (a -> UpdateT act m b) -> UpdateT act m b #

(>>) :: UpdateT act m a -> UpdateT act m b -> UpdateT act m b #

return :: a -> UpdateT act m a #

runUpdateT :: forall act m a. (Functor m, Action act) => UpdateT act m a -> StateOf act -> m (StateOf act, act, a) Source #

As runUpdate, except that it produces the results in the 'inner monad' of UpdateT.

Since: 1.0.0

Capability type class

class (Action act, Monad m) => MonadUpdate act (m :: Type -> Type) | m -> act where Source #

An mtl-style capability type class describing update monads in general, irrespective of their states and/or actions.

Laws

  1. send x *> send y = send (x <> y)

If you define update or request, ensure the following also hold:

  1. update mempty = pure ()
  2. request *> request = request
  3. update = void . send
  4. request = send mempty

Laws 4 and 5 form the default definitions of update and request respectively, which obey all these laws.

Since: 1.0.0

Minimal complete definition

send

Methods

send :: act -> m (StateOf act) Source #

Performs the given action on the state, returning the result.

Since: 1.0.0

update :: act -> m () Source #

Performs the given action, returning nothing.

Since: 1.0.0

request :: m (StateOf act) Source #

Retrieves the state without doing anything to it.

Since: 1.0.0

Instances

Instances details
MonadUpdate act m => MonadUpdate act (MaybeT m) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Methods

send :: act -> MaybeT m (StateOf act) Source #

update :: act -> MaybeT m () Source #

request :: MaybeT m (StateOf act) Source #

(Action act, Monad m) => MonadUpdate act (UpdateT act m) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Methods

send :: act -> UpdateT act m (StateOf act) Source #

update :: act -> UpdateT act m () Source #

request :: UpdateT act m (StateOf act) Source #

MonadUpdate act m => MonadUpdate act (ExceptT e m) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Methods

send :: act -> ExceptT e m (StateOf act) Source #

update :: act -> ExceptT e m () Source #

request :: ExceptT e m (StateOf act) Source #

MonadUpdate act m => MonadUpdate act (ReaderT r m) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Methods

send :: act -> ReaderT r m (StateOf act) Source #

update :: act -> ReaderT r m () Source #

request :: ReaderT r m (StateOf act) Source #

MonadUpdate act m => MonadUpdate act (StateT s m) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Methods

send :: act -> StateT s m (StateOf act) Source #

update :: act -> StateT s m () Source #

request :: StateT s m (StateOf act) Source #

MonadUpdate act m => MonadUpdate act (WriterT w m) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Methods

send :: act -> WriterT w m (StateOf act) Source #

update :: act -> WriterT w m () Source #

request :: WriterT w m (StateOf act) Source #

MonadUpdate act m => MonadUpdate act (RWST r w s m) Source #

Since: 1.0.0

Instance details

Defined in Control.Monad.Action

Methods

send :: act -> RWST r w s m (StateOf act) Source #

update :: act -> RWST r w s m () Source #

request :: RWST r w s m (StateOf act) Source #