Confusion about StateT, State and MonadState - haskell

I'm utterly confused between
newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}
and
type State s = StateT s Identity
and
class Monad m => MonadState s m | m -> s

Once upon a time, there was a State type:
-- Not the current definition.
newtype State s a = State {runState :: s -> (a, s)}
State s a values are, in essence, functions that take a state and produce a result and an updated state. Suitable Functor, Applicative and Monad instances make it possible to compose such functions in a more convenient manner, by making the tuple shuffling need to handle the (a, s) output implicit. With the help of a handful basic of operations that manipulate the state...
get = State $ \s -> (s, s)
put s = State $ \_ -> ((), s)
... it is possible to avoid any mention of the underlying s -> (a, s) type, and write code that feels stateful.
StateT s is a monad transformer patterned after State s:
newtype StateT s m a = StateT {runStateT :: s -> m (a, s)}
This transformer adds the state processing capabilities described above atop a base monad, m. It comes with Functor, Applicative and Monad instances, as well as versions of get and put.
If m, the base monad, in StateT s m is Identity, the dummy functor...
newtype Identity a = Identity {runIdentity :: a}
... we get something equivalent to plain old State s. That being so, transformers defines State as a synonym...
type State s = StateT s Identity
... rather than as a separate type.
As for MonadState, it caters to two different needs. Firstly, we can use the monad transformers machinery to have StateT s m as a base monad for some other transformer in a stack of transformers (arbitrary example: MaybeT (StateT Int IO)). In that case, though, lift from MonadTrans becomes necessary to use get and put. One way of using the operations directly in such cases is through MonadState: it provides them as methods...
-- Abridged class definition.
class Monad m => MonadState s m | m -> s where
get :: m s
put :: s -> m ()
state :: (s -> (a, s)) -> m a
... so that we can have instances for any combination of transformers involving StateT that we are interested in.
instance Monad m => MonadState s (StateT s m) where -- etc.
instance MonadState s m => MonadState s (MaybeT m) where -- etc.
-- And so forth
Secondly, if we want to have a state monad with an implementation different than the one in transformers, we can make it an instance of MonadState, so that we keep the same basic operations and, as long as we write type signatures in terms of MonadState, have it easier to change implementations if need be.

State is for your normal state monad. This is the simplest of the three. (In some older tutorials, you may see use of the State constructor, but this has been replaced with the state function, because State s is now a type alias for StateT s Identity.)
StateT is the monad transformer for the State monad. It adds a layer of generality by allowing you to put an arbitrary monad inside the state. This is useful for simple parsers, which could use e.g. StateT [Token] Maybe Result to represent the parsing as a stateful operation that could fail.
MonadState generalizes the situation even farther. There is an instance Monad m => MonadState s (StateT s m), but there are also instances, like one that allows you to perform stateful operations on monad transformers of StateT. All basic state functions (get, set, modify, etc.) can be used with an instance of MonadState.

Related

monad stack with multiple of the same transformer

I was trying to write my own monad transformers where it would make sense to have multiple of the same monad transformer on the stack with different types. The issue can be illustrated with the reader monad.
The reader monad is offered as a way to hold a read only context of a given type
ex1 :: Reader Bool Bool
ex1 = ask
or
ex2 :: Reader Char Bool
ex2 = pure True
monad transformers allow less restrictive assumptions about the underlining monad
ex3 :: (MonadReader Bool m) => m Bool
ex3 = ask
However, what if I want to have more than 1 read only environment? I can write a function like
ex4 :: (MonadReader Bool m, MonadReader Char m) => m Bool
ex4 = ask
However, as far as I can tell, there is no way to run ex4 since
class Monad m => MonadReader r m | m -> r
means that each MonadReader has a unique reading type. Is there a standard work around for multiple transformers on the same stack? Should I try to avoid this entirely?
Use a transformer and lift to get to your inner monad:
import Control.Monad.Trans.Reader
import Control.Monad.Trans.Class (lift)
type MyMonad a = ReaderT Bool (Reader Char) a
askBool :: MyMonad Bool
askBool = ask
askChar :: MyMonad Char
askChar = lift ask
The code you presented didn't use any monad transformer (directly). It used the reader monad (which happens to be a transformer applied to the identity monad) and the MonadReader type class. As you noticed, the type function implied by MonadReader can't result in two different outputs (the environment types) for the same input (the monad m).
One way to deal with it in a relatively straightforward way is to create a type that represents the state you wanna keep track of. Say you want to keep track of both a Bool and a Char as in your example
data MyState = MyState { getBool :: Bool, getChar :: Char }
f :: MonadReader MyState m => m Bool
f = asks getBool
Others may have more advanced solutions!

join function for two-kinded monads

I'm trying to get a better understanding of monads.
So I'm trying to write return, join, and bind implementations for several monads.
However when coming to two-kinded monads, I'm kind of confused
join :: m (m a) -> m a
m (m a) Implies monad wrapped inside of monad, but what value is implied if using two-kinded monads.
For example with the State Monad: s or a? What would the correct signature of join for the State Monad look like?
The state monad type is declared as State s a;
it only unifies with m a if m ~ State s.
join :: State s (State s a) -> State s a

Is there a library or typeclass for getting the transformer version of a monad?

In my current project I've run into the need to turn various monads into their transformer counterparts e.g.
stateT :: Monad m => State s a -> StateT s m a
stateT stf = StateT $ return . runState stf
It's trivial to write these utility functions for the monads I need, but I was wondering if there already exists a library that contains this functionality for the standard monads and maybe a typeclass that abstracts this sort of transformation. Something like
class (Monad f, MonadTrans t) => LiftTrans f t | f -> t where
liftT :: Monad m => f a -> t m a
("lift" is probably the wrong term to use here, but I wasn't sure what else to call it.)
Check out function hoist from the mmorph package.
Its signature is
hoist :: Monad m => (forall a. m a -> n a) -> t m b -> t n b
Meaning that it can change the base monad underlying a transformer.
Now, in the trasformers package, many "basic" monads are implemented as transformers applied to the Identity monad, like this:
type State s = StateT s Identity
Therefore, we can define the following function (taken form the Generalizing base monads section of the mmorph documentation):
import Data.Functor.Identity
generalize :: (Monad m) => Identity a -> m a
generalize m = return (runIdentity m)
and combine it with hoist:
hoist generalize :: (Monad m, MFunctor t) => t Identity b -> t m b
This method won't work for simple monads which are not defined as transformers applied to Identity, like the Maybe and Either monads. You are stuck with hoistMaybe and hoistEither for these.
You are trying to go the wrong way. If something is a transformer, than the plain version of it is the transformer applied to the Identity monad. (They are not always implemented like that directly, but should be equivalent modulo bottom.) But, not all monads are transformers (They need to be universally left or universally right adjoint in order to transform. [citation needed])
hoist and friends are super helpful, too, but I think it best to invert your process.

Stuck in the State Monad

I want to create a graph structure using an IntMap of nodes and unique keys. This topic has been covered well here and here. I understand how the state monad works by basically wrapping a function of state -> (val,state) in a newtype so we can create a monad instance for it. I have read about the topic quite a bit. I still cant seem to get my head around how I can get unique (or just incremental) values throughout the execution of my program. It's easy enough to get a run of successive IDs, but once I "runState" to get out of the monad it seems like I'm back where I started with having to keep track of the current ID. I feel like I'm stuck in the monad. The other option I considered was to keep the entire IntMap and current "next" ID as the state, but that seems very "imperative" and extreme. This question is very similar but did not get many answers(or maybe I'm just missing something obvious). What is the idiomatic way to utilize the state monad to get unique ID throughout a program execution? Thanks.
Let's imagine we were to IO-ify the State monad. What would that look like? Our pure State monad is just a newtype around:
s -> (a, s)
Well, the IO version might do a little bit of side effects before returning the final values, which would look like:
s -> IO (a, s)
That pattern is so common it has a name, specifically StateT:
newtype StateT s m a = StateT { runStateT :: s -> m (a, s) }
The name has a T at the end because it is a monad Transformer. We call m the "base monad" and StateT s m the "transformed" monad.
StateT s m is only a Monad if m is a Monad:
instance (Monad m) => Monad (StateT s m) where {- great exercise -}
However, in addition to that, all monad transformers implement the MonadTrans class, defined as follows:
class MonadTrans t where
lift :: (Monad m) => m a -> t m a
instance MonadTrans (StateT s) where {- great exercise -}
If t is StateT s, then lift's type specializes to:
lift :: m a -> StateT s m a
In other words, it lets us "lift" an action in the base monad to become an action in the transformed monad.
So, for your specific problem, you want the StateT (IntMap k v) IO monad, which extends IO with additional State. Then you can write your entire program in this monad:
main = flip runStateT (initialState :: IntMap k v) $ do
m <- get -- retrieve the map
lift $ print m -- lift an IO action
(k, v) <- lift readLn
put (insert k v m)
Notice that I still use get and put. That's because the transformers package implements all the concepts I described and it generalizes the signatures of get and put to be:
get :: (Monad m) => StateT s m s
put :: (Monad m) => s -> StateT s m ()
That means they automatically work within StateT. transformers then just defines State as:
type State s = StateT s Identity
That means that you can use get and put for both State and StateT.
To learn more about monad transformers, I highly recommend Monad Transformers - Step by Step.

Combining StateT and State monads

Lets say I have a function
f :: State [Int] Int
and a function:
g :: StateT [Int] IO Int
I want to use f in g and pass the state between them. Is there a library function for
StateT (return . runState f)? Or in general, given a monad transformer with a corresponding monad, is there a library function for it?
In even more general, what you're trying to do is apply a transformation to an inner layer of a transformer stack. For two arbitrary monads, the type signature might look something like this:
fmapMT :: (MonadTrans t, Monad m1, Monad m2) => (m1 a -> m2 a) -> t m1 a -> t m2 a
Basically a higher-level fmap. In fact, it would probably make even more sense to combine it with a map over the final parameter as well:
fmapMT :: (MonadTrans t, Monad m1, Monad m2) => (m1 a -> m2 b) -> t m1 a -> t m2 b
Clearly this isn't going to be possible in all cases, though when the "source" monad is Identity it's likely to be easier, but I can imagine defining another type class for the places it does work. I don't think there's anything like this in the typical monad transformer libraries; however, some browsing on hackage turns up something very similar in the Monatron package:
class MonadT t => FMonadT t where
tmap' :: FunctorD m -> FunctorD n -> (a -> b)
-> (forall x. m x -> n x) -> t m a -> t n b
tmap :: (FMonadT t, Functor m, Functor n) => (forall b. m b -> n b)
-> t m a -> t n a
tmap = tmap' functor functor id
In the signature for tmap', the FunctorD types are basically ad-hoc implementations of fmap instead of using Functor instances directly.
Also, for two Functor-like type constructors F and G, a function with a type like (forall a. F a -> G a) describes a natural transformation from F to G. There's quite possibly another implementation of the transformer map that you want somewhere in the category-extras package but I'm not sure what the category-theoretic version of a monad transformer would be so I don't know what it might be called.
Since tmap requires only a Functor instance (which any Monad must have) and a natural transformation, and any Monad has a natural transformation from the Identity monad provided by return, the function you want can be written generically for any instance of FMonadT as tmap (return . runIdentity)--assuming the "basic" monad is defined as a synonym for the transformer applied to Identity, at any rate, which is generally the case with transformer libraries.
Getting back to your specific example, note that Monatron does indeed have an instance of FMonadT for StateT.
What you are asking for is a mapping (known as a monad morphism) from a monad StateT m to StateT n. I'll be using the the mmorph library, which provides a very nice set of tools for working with monad morphisms.
To perform the State -> StateT m transform you are looking for, we'll start by defining a morphism to generalize the Identity monad embedded in State,
generalize :: Monad m => Identity a -> m a
generalize = return . runIdentity
Next we'll want to lift this morphism to act on the inner monad of your StateT. That is, we want a function which given a mapping from one monad to another (e.g. our generalize morphism), will give us a function acting on the base monad of a monad transformer, e.g. t Identity a -> t m a. You'll find this resembles the hoist function of mmorph's MFunctor class,
hoist :: Monad m => (forall a. m a -> n a) -> t m b -> t n b
Putting the pieces together,
myAction :: State s Int
myAction = return 2
myAction' :: Monad m => StateT s m Int
myAction' = hoist generalize myAction
Such a function is not definable for all monad transformers. The Cont r monad, for example, can't be lifted into ContT r IO because that would require turning a continuation in the IO monad (a -> IO r) into a pure continuation (a -> r).

Resources