miso
Copyright(C) 2016-2026 David M. Johnson
LicenseBSD3-style (see the file LICENSE)
MaintainerDavid M. Johnson <code@dmj.io>
Stabilityexperimental
Portabilitynon-portable
Safe HaskellSafe-Inferred
LanguageHaskell2010

Miso.State

Description

Overview

Miso.State re-exports the RWS combinators that are most useful inside an Effect handler. Because Effect is an RWS monad, the full MonadState, MonadReader, and MonadWriter interfaces are available without importing mtl directly.

This module is re-exported in its entirety by Miso, so most applications do not need to import it explicitly.

Quick start

import Miso          -- re-exports Miso.State
-- or
import Miso.State    -- explicit import

data Model = Model { _count :: Int } deriving (Eq)
data Action = Increment | Decrement | Reset | Log

update :: Action -> Effect p props Model Action
update Increment = modify (\m -> m { _count = _count m + 1 })
update Decrement = modify' (\m -> m { _count = _count m - 1 })
update Reset     = put (Model 0)
update Log       = do
  n <- gets _count
  io_ (consoleLog (ms n))

When using Miso.Lens or Miso.Lens.TH, the lens update operators (.=, +=, %=, …) are built directly on modify, so explicit calls to modify / put are rarely needed.

Exported combinators

See also

Synopsis

Documentation

ask :: MonadReader r m => m r #

Retrieves the monad environment.

asks #

Arguments

:: MonadReader r m 
=> (r -> a)

The selector function to apply to the environment.

-> m a 

Retrieves a function of the current environment.

modify :: MonadState s m => (s -> s) -> m () #

Monadic state transformer.

Maps an old state to a new state inside a state monad. The old state is thrown away.

     Main> :t modify ((+1) :: Int -> Int)
     modify (...) :: (MonadState Int a) => a ()

This says that modify (+1) acts over any Monad that is a member of the MonadState class, with an Int state.

modify' :: MonadState s m => (s -> s) -> m () #

A variant of modify in which the computation is strict in the new state.

Since: mtl-2.2

get :: MonadState s m => m s #

Return the state from the internals of the monad.

gets :: MonadState s m => (s -> a) -> m a #

Gets specific component of the state, using a projection function supplied.

put :: MonadState s m => s -> m () #

Replace the state inside the monad.

tell :: MonadWriter w m => w -> m () #

tell w is an action that produces the output w.

liftIO :: MonadIO m => IO a -> m a #

Lift a computation from the IO monad. This allows us to run IO computations in any monadic stack, so long as it supports these kinds of operations (i.e. IO is the base monad for the stack).

Example

Expand
import Control.Monad.Trans.State -- from the "transformers" library

printState :: Show s => StateT s IO ()
printState = do
  state <- get
  liftIO $ print state

Had we omitted liftIO, we would have ended up with this error:

• Couldn't match type ‘IO’ with ‘StateT s IO’
 Expected type: StateT s IO ()
   Actual type: IO ()

The important part here is the mismatch between StateT s IO () and IO ().

Luckily, we know of a function that takes an IO a and returns an (m a): liftIO, enabling us to run the program and see the expected results:

> evalStateT printState "hello"
"hello"

> evalStateT printState 3
3