Abstracting monad composition as a transformer - haskell

Sorry if the question seems a bit trivial... it is not for me.
I have happily composed the following monad:
type SB i a = ReaderT ( AlgRO i ) (State ( AlgState i ) ) a
which is, well, a well behaved monad. ReaderT is a monad transformer and State is the State monad, and AlgRO and AlgState are datatypes parametrized in i for mutable and read-only state, respectively. Now, if I want to make of that a neat monad transformer with newtype, something like this:
newtype SbT m i a = SbT {
runSbT:: m ( SB i a )
}
how should I proceed? I can not even manage to put together the bind method (of Monad typeclass), much less "lift" (of MonadTrans)... I guess that automatic derivation could help, but I want to understand how it works in this case.
Thanks in advance.

I don't think that definition for SbT is what you want. That defines functor composition, and assuming the m parameter is a Functor or Applicative, this should preserve those properties. But composition like that does not, in general, create a new monad out of two others. See this question for more on that subject.
So, how do you create the monad transformer you want, then? While monads don't compose directly, monad transformers can be composed. So to build a new transformer out of existing ones, you essentially just want to give a name to that composition. This differs from the newtype you have because there you're applying the m directly, instead of passing it in to the transformer stack.
One thing to keep in mind about defining monad transformers is that they necessarily work "backwards" in certain ways--when you apply a composite transformer to a monad, the "innermost" transformer gets the first crack at it, and the transformed monad it produces is what the next transformer out gets to work with, &c. Note that this isn't any different from the order you get when applying a composed function to an argument, e.g. (f . g . h) x gives the argument to h first, even though f is the "first" function in the composition.
Okay, so your composite transformer needs to take the monad it's applied to and pass it to the innermost transformer, which is, uhm.... oops, turns out that SB is already applied to a monad. No wonder this wasn't working. We'll need to remove that, first. Where is it? Not State--we could remove that, but we don't want to, because it's part of what you want. Hmm, but wait--what is State defined as, again? Oh yeah:
type State s = StateT s Identity
Aha, there we go. Let's get that Identity out of there. We go from your current definition:
type SB i a = ReaderT ( AlgRO i ) (State ( AlgState i ) ) a
To the equivalent form:
type SB i a = ReaderT ( AlgRO i ) ( StateT ( AlgState i ) Identity ) a
Then we kick the lazy bum out:
type SB' i m a = ReaderT ( AlgRO i ) ( StateT ( AlgState i ) m ) a
type SB i a = SB' i Identity a
But now SB' looks suspiciously like a monad transformer definition, and with good reason, because it is. So we recreate the newtype wrapper, and toss a few instances out there:
newtype SbT i m a = SbT { getSB :: ReaderT ( AlgRO i ) ( StateT ( AlgState i ) m ) a }
instance (Functor m) => Functor (SbT i m) where
fmap f (SbT sb) = SbT (fmap f sb)
instance (Monad m) => Monad (SbT i m) where
return x = SbT (return x)
SbT m >>= k = SbT (m >>= (getSB . k))
instance MonadTrans (SbT i) where
lift = SbT . lift . lift
runSbT :: SbT i m a -> AlgRO i -> AlgState i -> m (a, AlgState t)
runSbT (SbT m) e s = runStateT (runReaderT m e) s
A couple things to take note of: The runSbT function here is not the field accessor, but rather a composed "run" function for each transformer in the stack that we know of. Similarly, the lift function has to lift once for the two inner transformers, then add the final newtype wrapper. Both of these make it work as a single monad transformer, hiding the fact that it's actually a composite.
If you'd like, it should be straightforward to write instances for MonadReader and MonadState as well, by lifting the instances for the composed transformers.

Did you intend to wrap an additional m around things in your newtype? I would suggest the following:
newtype Sb i a = Sb { runSb :: SB i a }
...which should make your instance Monad (Sb i) a bit easier to write. If you're really trying to write a monad transformer, then you should use transformers all the way down; for example,
type SBT m i a = ReaderT (AlgRO i) (StateT (AlgState i) m) a
newtype SbT m i a = SbT { runSbT :: SBT m i a }
As a second point of interest, it's often preferable to η-reduce type synonyms (since they must always be "fully applied"); doing this with SB and SBT would look like this:
type SB i = ReaderT (AlgRO i) (State (AlgState i))
type SBT m i = ReaderT (AlgRO i) (StateT (AlgState i) m)

Related

Haskell - MonadState

So I have recently been looking at state monads because I want to build a parser combinator library in haskell.
I came across a typeclass known as MonadState, I was wondering what is the point of this typeclass and where would you use it?
MonadState abstracts out the get and put functions so that they work not just for one type, but for any type that can act as a state monad. It's primarily to make monad transformers work.
Without going into too much detail, let's just assume you know that StateT exists: it takes one monad and returns a new monad that can act as state. (I'll ignore the difference between lazy and strict state monads here). A monad that handles state can then be defined by applying StateT to the Identity monad:
newtype State s = StateT s Identity
As long as the input type is a monad, we can provide a MonadState instance for the monad returned by StateT:
-- Add state to any monad
instance Monad m => MonadState s (StateT s m) where
...
This says that applying StateT to any monad (not just Identity) produces a monad that can be treated as a state monad.
Further, you can say that anything that wraps a state monad is also a state monad, as long as it implements MonadState:
-- Add Maybe to a state monad, it's still a state monad
instance MonadState s m => MonadState s (MaybeT m) where
...
-- Add Writer to a state monad, it's still a state monad
instance (Monoid w, MonadState s m) => MonadState s (WriterT w m) where
...
MonadState abstracts the state monad (as if this stuff wasn't abstract enough, right?). Instead of requiring a concrete type State with a Monad instance, it lets us use any Monad we like, provided we can provide appropriate get and put functions. In particular, we can use StateT which lets us combine effects.
simple example combining State and IO:
tick :: (MonadIO m, MonadState Int m) => m ()
tick = do
x <- get
liftIO $ putStrLn ("incrementing " ++ (show x))
put (x+1)
> runStateT (tick >> tick >> tick >> tick) 5
incrementing 5
incrementing 6
incrementing 7
incrementing 8
((),9)

Why are monad transformers different to stacking monads?

In many cases, it isn't clear to me what is to be gained by combining two monads with a transformer rather than using two separate monads. Obviously, using two separate monads is a hassle and can involve do notation inside do notation, but are there cases where it just isn't expressive enough?
One case seems to be StateT on List: combining monads doesn't get you the right type, and if you do obtain the right type via a stack of monads like Bar (where Bar a = (Reader r (List (Writer w (Identity a))), it doesn't do the right thing.
But I'd like a more general and technical understanding of exactly what monad transformers are bringing to the table, when they are and aren't necessary, and why.
To make this question a little more focused:
What is an actual example of a monad with no corresponding transformer (this would help illustrate what transformers can do that just stacking monads can't).
Are StateT and ContT the only transformers that give a type not equivalent to the composition of them with m, for an underlying monad m (regardless of which order they're composed.)
(I'm not interested in particular implementation details as regards different choices of libraries, but rather the general (and probably Haskell independent) question of what monad transformers/morphisms are adding as an alternative to combining effects by stacking a bunch of monadic type constructors.)
(To give a little context, I'm a linguist who's doing a project to enrich Montague grammar - simply typed lambda calculus for composing word meanings into sentences - with a monad transformer stack. It would be really helpful to understand whether transformers are actually doing anything useful for me.)
Thanks,
Reuben
To answer you question about the difference between Writer w (Maybe a) vs MaybeT (Writer w) a, let's start by taking a look at the definitions:
newtype WriterT w m a = WriterT { runWriterT :: m (a, w) }
type Writer w = WriterT w Identity
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
Using ~~ to mean "structurally similar to" we have:
Writer w (Maybe a) == WriterT w Identity (Maybe a)
~~ Identity (Maybe a, w)
~~ (Maybe a, w)
MaybeT (Writer w) a ~~ (Writer w) (Maybe a)
== Writer w (Maybe a)
... same derivation as above ...
~~ (Maybe a, w)
So in a sense you are correct -- structurally both Writer w (Maybe a) and MaybeT (Writer w) a
are the same - both are essentially just a pair of a Maybe value and a w.
The difference is how we treat them as monadic values.
The return and >>= class functions do very different things depending
on which monad they are part of.
Let's consider the pair (Just 3, []::[String]). Using the association
we have derived above here's how that pair would be expressed in both monads:
three_W :: Writer String (Maybe Int)
three_W = return (Just 3)
three_M :: MaybeT (Writer String) Int
three_M = return 3
And here is how we would construct a the pair (Nothing, []):
nutin_W :: Writer String (Maybe Int)
nutin_W = return Nothing
nutin_M :: MaybeT (Writer String) Int
nutin_M = MaybeT (return Nothing) -- could also use mzero
Now consider this function on pairs:
add1 :: (Maybe Int, String) -> (Maybe Int, String)
add1 (Nothing, w) = (Nothing w)
add1 (Just x, w) = (Just (x+1), w)
and let's see how we would implement it in the two different monads:
add1_W :: Writer String (Maybe Int) -> Writer String (Maybe Int)
add1_W e = do x <- e
case x of
Nothing -> return Nothing
Just y -> return (Just (y+1))
add1_M :: MaybeT (Writer String) Int -> MaybeT (Writer String) Int
add1_M e = do x <- e; return (e+1)
-- also could use: fmap (+1) e
In general you'll see that the code in the MaybeT monad is more concise.
Moreover, semantically the two monads are very different...
MaybeT (Writer w) a is a Writer-action which can fail, and the failure is
automatically handled for you. Writer w (Maybe a) is just a Writer
action which returns a Maybe. Nothing special happens if that Maybe value
turns out to be Nothing. This is exemplified in the add1_W function where
we had to perform a case analysis on x.
Another reason to prefer the MaybeT approach is that we can write code
which is generic over any monad stack. For instance, the function:
square x = do tell ("computing the square of " ++ show x)
return (x*x)
can be used unchanged in any monad stack which has a Writer String, e.g.:
WriterT String IO
ReaderT (WriterT String Maybe)
MaybeT (Writer String)
StateT (WriterT String (ReaderT Char IO))
...
But the return value of square does not type check against Writer String (Maybe Int) because square does not return a Maybe.
When you code in Writer String (Maybe Int), you code explicitly reveals
the structure of monad making it less generic. This definition of add1_W:
add1_W e = do x <- e
return $ do
y <- x
return $ y + 1
only works in a two-layer monad stack whereas a function like square
works in a much more general setting.
What is an actual example of a monad with no corresponding transformer (this would help illustrate what transformers can do that just stacking monads can't).
IO and ST are the canonical examples here.
Are StateT and ContT the only transformers that give a type not equivalent to the composition of them with m, for an underlying monad m (regardless of which order they're composed.)
No, ListT m a is not (isomorphic to) [m a]:
newtype ListT m a =
ListT { unListT :: m (Maybe (a, ListT m a)) }
To make this question a little more focused:
What is an actual example of a monad with no corresponding transformer (this would help illustrate what transformers can do that just stacking monads can't).
There are no known examples of a monad that lacks a transformer, as long as the monad is defined explicitly as a pure lambda-calculus term, with no side effects and no external libraries being used. The Haskell monads such as IO and ST are essentially interfaces to an external library defined by low-level code. Those monads cannot be defined by pure lambda-calculus, and their monad transformers probably do not exist.
Even though there are no known explicit examples of monads without transformers, there is also no known general method or algorithm for obtaining a monad transformer for a given monad. If I define some complicated monad, for example like this code in Haskell:
type D a = Either a ((a -> Bool) -> Maybe a)
then it is far from obvious how to define a transformer for the monad D.
This D a may look a contrived and artificial example (and it's also not obvious why it is a monad) but there might be legitimate cases for using that monad, which is a "free pointed monad on the Search monad on Maybe".
To clarify: A "search monad on n" is the type S n q a = (a -> n q) -> n a where n is another monad and q is a fixed type.
A "free pointed monad on M" is the type P a = Either a (M a) where M is another monad.
In any case, I just want to illustrate the point. I don't think it would be easy for anyone to come up with the monad transformer for D and then to prove that it satisfies the laws of monad transformers. There is no known algorithm that takes the code of D and outputs the code of its transformer.
Are StateT and ContT the only transformers that give a type not equivalent to the composition of them with m, for an underlying monad m (regardless of which order they're composed.)
Monad transformers are necessary because stacking two monads is not always a monad. Most "simple" monads, like Reader, Writer, Maybe, etc., stack with other monads in a particular order. But the result of stacking, say, Writer + Reader + Maybe, is a more complicated monad that no longer allows stacking with new monads.
There are several examples of monads that do not stack at all: State, Cont, List, Free monads, the Codensity monad, and a few other, less well known monads, like the "free pointed" monad shown above.
For each of those "non-stacking" monads, one needs to guess the correct monad transformer somehow.
I have studied this question for a while and I have assembled a list of techniques for creating monad transformers, together with full proofs of all laws. There doesn't seem to be any system to creating a monad transformer for a specific monad. I even found a couple of monads that have two inequivalent transformers.
Generally, monad transformers can be classified in 6 different families:
Functor composition in one or another order: EitherT, WriterT, ReaderT and a generalization of Reader to a special class of monads, called "rigid" monads. An example of a "rigid" monad is Q a = (H a) -> a where H is an arbitrary (but fixed) contravariant functor.
The "adjunction recipe": StateT, ContT, CodensityT, SearchT, which gives transformers that are not functorial.
The "recursive recipe": ListT, FreeT
Cartesian product of monads: If M and N are monads then their Cartesian product, type P a = (M a, N a) is also a monad whose transformer is the Cartesian product of transformers.
The free pointed monad: P a = Either a (M a) where M is another monad. For that monad, the transformer's type is m (Either a (MT m a)) where MT is the monad M's transformer.
Monad stacks, that is, monads obtained by applying one or more monad transformers to some other monad. A monad stack's transformer is build via a special recipe that uses all the transformers of the individual monads in the stack.
There may be monads that do not fit into any of these cases, but I have seen no examples so far.
Details and proofs of these constructions of monad transformers are in my draft book here https://github.com/winitzki/sofp

State monad with Predicates

I'm attempting to create something that looks a lot like the State monad, but also carries a list of predicates and accompanying transition functions over the state. The basic steps for computation I'm envisioning are like follows:
Foo (state, [(pred, t)]) >>= f. Apply f to s, yielding s'. Then apply each predicate to s'. For each predicate that matches, apply the associated transition function to the state in sequence. E.g. suppose [(p1, t1), (p2, t2), (p3, t3)], f, and s. If after f s yields s', p1 s' and p3 s' both return True, you would perform t1 s' yielding s'' and then perform t3 s'' yielding s''', the result of the computation.
There's a lot of moving parts here, and I feel as if the correct approach would be to build this on top of the StateT transformer or the State monad, however I can't figure out where to start.
I feel as if this isn't terribly clear. Any clarifications that would make this clearer are much appreciated.
I don't think you can make the monad you're asking for. As I was mentioning in my discussion with jozefg, we have two monad laws that say
f >=> return = f
return >=> f = f
which means that nothing "interesting" can happen at a binding location. In particular, we can't run a state-transition function at each binding, because then f >=> return will run that transition function and f won't, and these laws will be broken.
However, that doesn't stop us from making a monadic action that runs the state transitions on our behalf. So I'll sketch the idea for how to design a monad that tracks such transitions and runs them on demand. You'll surely need to flesh out the API some if you want it to be useful. The basic idea is that instead of just an s as state, we'll store both an s and a transition table. First, some boilerplate.
{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses #-}
import Control.Arrow
import Control.Applicative
import Control.Monad.State
For now, let's just work with s -> s transitions. You can implement them however you like -- including looking in a list of predicates and transitions and picking out the ones you want to run, if that's your cup of tea. But that's orthogonal to getting the rest of the idea right. We'll define our new type and give it a Monad instance that just dispatches to the underlying type.
newtype TStateT s m a = TStateT { unTStateT :: StateT (s, s -> s) m a }
deriving (Functor, Applicative, Monad)
The MonadState instance is a bit trickier than just using deriving, but still pretty straightforward. Presumably publically we want to pretend that only s is part of the state, so we need to focus our attention a bit. We'll also give the runStateT analog, and pick a sane initial transition function. (We'll give a way to modify this choice later.)
instance Monad m => MonadState s (TStateT s m) where
state f = TStateT (state (\(s, t) -> let (v, s') = f s in (v, (s', t))))
runTStateT :: Functor m => TStateT s m a -> s -> m (a, s)
runTStateT m s = second fst <$> runStateT (unTStateT m) (s, id)
Now comes the interesting bit. The superpower of TStateT is that it has some transitions it can run at any time. So let's provide a way to run them and a way to modify the transition table.
step :: Monad m => TStateT s m ()
step = TStateT (gets snd) >>= modify
modifyTransitions :: Monad m => ((s -> s) -> (s -> s)) -> TStateT s m ()
modifyTransitions = TStateT . modify . second
And that's pretty much everything!

MonadTransControl instance for ProxyFast/ProxyCorrect

Using pipes, I'm trying to write an instance of MonadTransControl for the ProxyFast or ProxyCorrect type. This is what I've got:
instance MonadTransControl (ProxyFast a' a b' b) where
data StT (ProxyFast a' a b' b) a = StProxy { unStProxy :: ProxyFast a' a b' b Identity a}
liftWith = undefined
restoreT = undefined
I have no idea how to write liftWith or restoreT. The instances for the other monad transformers all use a function that "swaps" the monads, for example EitherT e m a -> m (EitherT e Identity a), but I couldn't find any such function in pipes. How does the instance for MonadTransControl for ProxyCorrect / ProxyFast look like? Or is it impossible to write one? (If yes, is it possible in pipes 4.0?)
Thanks for the link, and now I can give a better answer.
No, there is no way to implement this, using either version of pipes. The reason why is that MonadTransControl expects a monad transformer to be built on top of a single layer of the underlying base monad. This is true for all the monad transformers that MonadTransControl currently implements, such as:
ErrorT ~ m (Either e r)
StateT ~ s -> m (r, s)
WriterT ~ m (r, w)
ReaderT ~ i -> m r
ListT ~ m [r] -- This version of ListT is wrong, and the true ListT
-- would not work for `MonadTransControl`
However, a Proxy does not wrap a single layer of the base monad. This is true for both pipes versions where you can nest as many layers of the base monad as you want.
In fact, any monad transformer that nests the base monad multiple times will defy a MonadTransControl instance, such as:
FreeT -- from the `free` package
ListT -- when done "right"
ConduitM -- from the `conduit` package
However, just because pipes does not implement MonadTransControl doesn't mean that all hope is lost. pipes-safe implements many of the operations that one would typically expect from MonadTransControl, such as bracketing resource acquisitions, so if you can elaborate on your specific use case I can tell you more if there is an appropriate pipes-based solution for your problem.

Transformation under Transformers

I'm having a bit of difficulty with monad transformers at the moment. I'm defining a few different non-deterministic relations which make use of transformers. Unfortunately, I'm having trouble understanding how to translate cleanly from one effectful model to another.
Suppose these relations are "foo" and "bar". Suppose that "foo" relates As and Bs to Cs; suppose "bar" relates Bs and Cs to Ds. We will define "bar" in terms of "foo". To make matters more interesting, the computation of these relations will fail in different ways. (Since the bar relation depends on the foo relation, its failure cases are a superset.) I therefore give the following type definitions:
data FooFailure = FooFailure String
data BarFailure = BarSpecificFailure | BarFooFailure FooFailure
type FooM = ListT (EitherT FooFailure (Reader Context))
type BarM = ListT (EitherT BarFailure (Reader Context))
I would then expect to be able to write the relations with the following function signatures:
foo :: A -> B -> FooM C
bar :: B -> C -> BarM D
My problem is that, when writing the definition for "bar", I need to be able to receive errors from the "foo" relation and properly represent them in "bar" space. So I'd be fine with a function of the form
convert :: (e -> e') -> ListT (EitherT e (Reader Context) a
-> ListT (EitherT e' (Reader Context) a
I can even write that little beast by running the ListT, mapping on EitherT, and then reassembling the ListT (because it happens that m [a] can be converted to ListT m a). But this seems... messy.
There's a good reason I can't just run a transformer, do some stuff under it, and generically "put it back"; the transformer I ran might have effects and I can't magically undo them. But is there some way in which I can lift a function just far enough into a transformer stack to do some work for me so I don't have to write the convert function shown above?
I think convert is a good answer, and using Control.Monad.Morph and Control.Monad.Trans.Either it's (almost) really simple to write:
convert :: (Monad m, Functor m, MFunctor t)
=> (e -> e')
-> t (EitherT e m) b -> t (EitherT e' m) b
convert f = hoist (bimapEitherT f id)
the slight problem is that ListT isn't an instance of MFunctor. I think this is the author boycotting ListT because it doesn't follow the monad transformer laws though because it's easy to write a type-checking instance
instance MFunctor ListT where hoist nat (ListT mas) = ListT (nat mas)
Anyway, generally take a look at Control.Monad.Morph for dealing with natural transformations on (parts of) transformer stacks. I'd say that fits the definition of lifting a function "just enough" into a stack.

Resources