haskell join multi-level monad - haskell

I'm learning haskell, and trying to use applicative functors as much as possible instead of monad. It is very neat and easy to compose. However, occasionally some types like IO [IO [a]] or IO Maybe IO Maybe a will rise in the code, which cause me big trouble. Apparently monad become inevitable in these scenarios.
I know there is a flat operation like join:: m (m a) -> m a for single level monads. Is there anything similar for multi-level monads? Anything in monad transformers?
Thanks a lot!

If you note that m (n _) is a monad transformer then you can define this operation. This is certainly the case when we notice that IO (Maybe a) is the same as MaybeT IO a: we then just use MaybeT's join. We can do this in no small part due to the fact that Maybe and IO "layer" especially nicely.
On the other hand, not all "composed" monads are monad transformers. In particular, IO [a] isn't really one. The true ListT transformer we'd like to have and to join looks like
newtype ListT m a = ListT { runListT :: m (Maybe (a, ListT m a)) }
It is the case that we can turn IO [a] into ListT IO a and visa-versa, but it is not the case that these operations invert one another. Truly, IO [a] is not a monad in its own right and cannot be joined.

Monads do not commute in general, but you can provide all particular cases, that you need:
{-# LANGUAGE MultiParamTypeClasses #-}
import Control.Monad
class (Monad m, Monad n) => Swappable m n where
swap :: m (n a) -> n (m a)
instance Swappable [] IO where
swap = sequence
instance Swappable Maybe IO where
swap Nothing = return Nothing
swap (Just mx) = fmap return mx
cut :: Swappable m n => m (n (m a)) -> n (m a)
cut = liftM join . swap
squash :: Swappable m n => n (m (n (m a))) -> n (m a)
squash = (>>= cut)
An example:
x :: IO [IO [()]]
x = return $ map (\s -> putStrLn s >> return [()]) ["ab","c"]
y :: IO (Maybe (IO (Maybe ())))
y = return $ Just $ putStrLn "z" >> return (Just ())
main = squash x >> squash y
prints
ab
c
z
EDIT
You can avoid defining new typeclass by providing an instance of Traversable (there are instances for Maybe and [] in Data.Traversable):
import Data.Traversable as T
import Control.Monad
cut :: (Traversable t, Monad t, Monad m) => t (m (t a)) -> m (t a)
cut = liftM join . T.sequence
squash :: (Traversable t, Monad t, Monad m) => m (t (m (t a))) -> m (t a)
squash = (>>= cut)

Related

Lifting a complete monadic action to a transformer (>>= but for Monad Transformers)

I looked hard to see if this may be a duplicate question but couldn't find anything that addressed specifically this. My apologies if there actually is something.
So, I get how lift works, it lifts a monadic action (fully defined) from the outer-most transformer into the transformed monad. Cool.
But what if I want to apply a (>>=) from one level under the transformer into the transformer? I'll explain with an example.
Say MyTrans is a MonadTrans, and there is also an instance Monad m => Monad (MyTrans m). Now, the (>>=) from this instance will have this signature:
instance Monad m => Monad (MyTrans m) where
(>>=) :: MyTrans m a -> (a -> MyTrans m b) -> MyTrans m b
but what I need is something like this:
(>>=!) :: Monad m => MyTrans m a -> (m a -> MyTrans m b) -> MyTrans m b
In general:
(>>=!) :: (MonadTrans t, Monad m) => t m a -> (m a -> t m b) -> t m b
It looks like a combination of the original (>>=) and lift, except it really isn't. lift can only be used on covariant arguments of type m a to transform them into a t m a, not the other way around. In other words, the following has the wrong type:
(>>=!?) :: Monad m => MyTrans m a -> (a -> m b) -> MyTrans m b
x >>=!? f = x >>= (lift . f)
Of course a general colift :: (MonadTrans t, Monad m) => t m a -> m a makes absolutely zero sense, because surely the transformer is doing something that we cannot just throw away like that in all cases.
But just like (>>=) introduces contravariant arguments into the monad by ensuring that they will always "come back", I thought something along the lines of the (>>=!) function would make sense: Yes, it in some way makes an m a from a t m a, but only because it does all of this within t, just like (>>=) makes an a from an m a in some way.
I've thought about it and I don't think (>>=!) can be in general defined from the available tools. In some sense it is more than what MonadTrans gives. I haven't found any related type classes that offer this either. MFunctor is related but it is a different thing, for changing the inner monad, but not for chaining exclusively transformer-related actions.
By the way, here is an example of why you would want to do this:
EDIT: I tried to present a simple example but I realized that that one could be solved with the regular (>>=) from the transformer. My real example (I think) cannot be solved with this. If you think every case can be solved with the usual (>>=), please do explain how.
Should I just define my own type class for this and give some basic implementations? (I'm interested in StateT, and I'm almost certain it can be implemented for it) Am I doing something in a twisted way? Is there something I overlooked?
Thanks.
EDIT: The answer provided by Fyodor matches the types, but does not do what I want, since by using pure, it is ignoring the monadic effects of the m monad. Here is an example of it giving the wrong answer:
Take t = StateT Int and m = [].
x1 :: StateT Int [] Int
x1 = StateT (\s -> [(1,s),(2,s),(3,s)])
x2 :: StateT Int [] Int
x2 = StateT (\s -> [(1,s),(2,s),(3,s),(4,s))])
f :: [Int] -> StateT Int [] Int
f l = StateT (\s -> if (even s) then [] else (if (even (length l)) then (fmap (\z -> (z,z+s)) l) else [(123,123)]))
runStateT (x1 >>= (\a -> f (pure a))) 1 returns [(123,123),(123,123),(123,123)] as expected, since both 1 is odd and the list in x1 has odd length.
But runStateT (x2 >>= (\a -> f (pure a))) 1 returns [(123,123),(123,123),(123,123),(123,123)], whereas I would have expected it to return [(1,2),(2,3),(3,4),(4,5)], since the 1 is odd and the length of the list is even. Instead, the evaluation of f is happening on the lists [(1,1)], [(2,1)], [(3,1)] and [(4,1)] independently, due to the pure call.
This can be very trivially implemented via bind + pure. Consider the signature:
(>>=!) :: (Monad m, MonadTrans t) => t m a -> (m a -> t m a) -> t m a
If you use bind on the first argument, you get yourself a naked a, and since m is a Monad, you can trivially turn that naked a into an m a via pure. Therefore, the straightforward implementation would be:
(>>=!) x f = x >>= \a -> f (pure a)
And because of this, bind is always strictly more powerful than your proposed new operation (>>=!), which is probably the reason it doesn't exist in the standard libraries.
I think it may be possible to propose more clever interpretations of (>>=!) for some specific transformers or specific underlying monads. For example, if m ~ [], one might imagine passing the whole list as m a instead of its elements one by one, as my generic implementation above would do. But this sort of thing seems too specific to be implemented in general.
If you have a very specific example of what you're after, and you can show that my above general implementation doesn't work, then perhaps I can provide a better answer.
Ok, to address your actual problem from the comments:
I have a function f :: m a -> m b -> m c that I want to transform into a function ff :: StateT s m a -> StateT s m b -> StateT s m c
I think looking at this example may illustrate the difficulty better. Consider the required signature:
liftish :: Monad m => (m a -> m b -> m c) -> StateT m a -> StateT m b -> StateT m c
Presumably, you'd want to keep the effects of m that are already "imprinted" within the StateT m a and StateT m b parameters (because if you don't - my simple solution above will work). To do this, you can "unwrap" the StateT via runStateT, which will get you m a and m b respectively, which you can then use to obtain m c:
liftish f sa sb = do
s <- get
let ma = fst <$> runStateT sa s
mb = fst <$> runStateT sb s
lift $ f ma mb
But here's the trouble: see those fst <$> in there? They are throwing away the resulting state. The call to runStateT sa s results not only in the m a value, but also in the new, modified state. And same goes for runStateT sb s. And presumably you'd want to get the state that resulted from runStateT sa and pass it to runStateT sb, right? Otherwise you're effectively dropping some state mutations.
But you can't get to the resulting state of runStateT sa, because it's "wrapped" inside m. Because runStateT returns m (a, s) instead of (m a, s). If you knew how to "unwrap" m, you'd be fine, but you don't. So the only way to get that intermediate state is to run the effects of m:
liftish f sa sb = do
s <- get
(c, s'') <- lift $ do
let ma = runStateT sa s
(_, s') <- ma
let mb = runStateT sb s'
(_, s'') <- mb
c <- f (fst <$> ma) (fst <$> mb)
pure (c, s'')
put s''
pure c
But now see what happens: I'm using ma and mb twice: once to get the new states out of them, and second time by passing them to f. This may lead to double-running effects or worse.
This problem of "double execution" will, I think, show up for any monad transformer, simply because the transformer's effects are always wrapped inside the underlying monad, so you have a choice: either drop the transformer's effects or execute the underlying monad's effects twice.
I think what you "really want" is
(>>>==) :: MyTrans m a -> (forall b. m b -> MyTrans n b) -> MyTrans n a
-- (=<<) = flip (>>=) is nicer to think about, because it shows that it's a form of function application
-- so let's think about
(==<<<) :: (forall a. m b -> MyTrans n b) -> (forall a. MyTrans m a -> MyTrans n a)
-- hmm...
type (~>) a b = forall x. a x -> b x
(==<<<) :: (m ~> MyTrans n) -> MyTrans m ~> MyTrans n
-- look familiar?
That is, you are describing monads on the category of monads.
class MonadTrans t => MonadMonad t where
-- returnM :: m ~> t m
-- but that's just lift, therefore the MonadTrans t superclass
-- note: input must be a monad homomorphism or else all bets are off
-- output is also a monad homomorphism
(==<<<) :: (Monad m, Monad n) => (m ~> t n) -> t m ~> t n
instance MonadMonad (StateT s) where
-- fairly sure this is lawful
-- EDIT: probably not
f ==<<< StateT x = do
(x, s) <- f <$> x <$> get
x <$ put s
However, making your example work is just not going to happen. It is too unnatural. StateT Int [] is the monad for programs that nondeterministically evolve the state. It is an important property of that monad that each "parallel universe" receives no communication from the others. The specific operation you are performing will probably not be provided by any useful typeclass. You can only do part of it:
f :: [] ~> StateT Int []
f l = StateT \s -> if odd s && even (length l) then fmap (\x -> (x, s)) l else []
f ==<<< x1 = []
f ==<<< x2 = [(1,1),(2,1),(3,1),(4,1)]

Function in Haskell to map over a MonadTrans?

I have recently decided to start using monad transformations instead of stacking my monads, since it seems it's the right thing to do. I wasn't really stacking many monads before anyway. I get (I think) the idea behind it and the lift function, that, as I understand it, acts as a sort of return for the transformation (puts something from the underlying monad into the transformed monad).
So far so good, but I don't see anything similar to an fmap function for monad transformations. Let me give you an example. Say I have a custom monad, m, and I use a StateT transformation on it, therefore using the type StateT s m a instead of m (State s a).
Now, it so happens that in my monad m, I have a function that transforms the monadic element (in fact it is one of the constructors of the monad, if you need details I can give) while keeping in some sense the underlying values: myFunc :: m a -> m a.
So I'm building a recursive function recFunc :: State s a -> [t] -> m (State s a) that looks similar to something like this:
recFunc :: State s a -> [t] -> m (State s a)
recFunc x [] = return x
recFunc x (t:ts) = myFunc (recFunc x ts)
But if I try to replicate this using monad transformations, I run into problems because I can find no way to plug in myFunc into the mix. It does not matter whether you write the input as State s a or as StateT s Identity a (which would be algebraically more precise?)
recFuncT :: StateT s Identity a -> [t] -> StateT s m a
recFuncT x [] = ???
recFuncT x (t:ts) = ????? where rec = recFuncT x ts
So what I'm looking for is something like the (invented, and don't know how I would implement, if possible) following functions:
transmap :: (MonadTrans t, Monad m) => (forall b. m b -> m b) -> t m a -> t m a
transmap = ???
transreturn :: (MonadTrans t, Monad m) => m (t Identity a) -> t m a
transreturn = ???
I have the feeling I should be able to define these using lift, but I don't see how, to be honest.
If I had them, then I could do this:
recFuncT :: StateT s Identity a -> [t] -> StateT s m a
recFuncT x [] = transreturn (return x)
recFuncT x (t:ts) = transmap myFunc (recFuncT x ts)
Maybe what I really want is something more basic. I want the assumed isomorphism between t m a and m (t Identity a) to be explicit, so I'm looking for functions:
fromTrans :: t m a -> m (t Identity a)
toTrans :: m (t Identity a) -> t m a
As far as I understand monad transformers, these functions should always exist and be fairly straightforward, right?
With these I could obviously implement transmap and transreturn:
transmap :: (MonadTrans t, Monad m) => (forall b. m b -> m b) -> t m a -> t m a
transmap f x = toTrans (f (fromTrans x))
transreturn :: (MonadTrans t, Monad m) => m (t Identity a) -> t m a
transreturn = toTrans
I am sure there is something obvious that I am overlooking. Please point at it for me.
Thanks.
It appears that one concept you're seeking can be found in the mmorph package:
class MFunctor t where
-- The argument is generally required to be a monad morphism,
-- but some instances will work sensibly when it's not.
hoist :: Monad m => (forall x. m x -> n x) -> t m a -> t n a
This is a little more general than your version because it allows the underlying monad to be replaced.
From the discussion in the comments, it sounds like what you really want is a monad transformer for your custom monad that is then applied to the base monad State. In other words, to the extent that your custom monad is "nearly" a list:
newtype Listish a = Listish [a]
its transformer version would have type:
newtype ListishT m a = ListishT [m a]
and so your final monad transformer stack would be:
type M s = ListishT (State s)
which is isomorphic to your monad stack
[State s a] AKA Listish (State s a)
Be sure not to over-generalize the pattern for creating a transformer from an underlying monad, however. While transformers for some monads:
newtype List a = List [a]
newtype Reader r a = Reader (r -> a)
are sensibly derived by replacing "a" with "m a":
newtype ListT m a = ListT [m a]
newtype ReaderT r m a = ReaderT (r -> m a)
transformers for other types are derived differently. For example:
newtype State s a = State (s -> (a, s))
newtype Writer w a = Writer (a, w)
give:
newtype StateT s a = StateT (s -> m (a, s))
-- **NOT** StateT (s -> (m a, s))
newtype WriterT s a = WriterT (m (a, w))
-- **NOT** WriterT (m a, w)
In particular, there is no monad transformer for IO, because the simple substitution
newtype BadIOT m a = BadIOT (IO (m a))
is, as you point out, silly.
EDIT: All of the below makes no sense. I leave it strikedthrough. Good answer below.
For the record, my final solution was neither to use or implement a monad transformer, and instead simply implement the following function: (my custom monad is called EnumProc):
(..>>=) :: Monad m => EnumProc (m a) -> (a -> m b) -> EnumProc (m b)
en ..>>= f = en <$> (>>= f)
infixl 7 ..>>=
This allows me to deal with monadic computations inside my monad while keeping the outside monad structure. I was surprised myself when an fmap sufficed.
I then use EnumProc (State s a) as type throughout.
After a while, I finally came up with exactly what I was looking for since the beginning. I can use StateT exactly the way I wanted, and it has exactly the semantics I thought it had, but I did not explain it well (and put mistakes in what I wrote).
Going back to my original post, I need not have a State as input, the State/StateT monad already includes the input in the monadic element. So what I needed was a function recFuncT :: [t] -> StateT s m a that behaved equivalently to the following non-transformer one:
recFunc :: a -> [t] -> m (State s a)
recFunc x [] = return (return x)
recFunc x (t:ts) = myFunc (recFunc x ts)
It can be implemented directly, using the constructor StateT and runStateT. Here it is:
recFuncT :: a -> [t] -> StateT m s a
recFuncT x [] = return x
recFuncT x (t:ts) = StateT (\s -> myFunc (runStateT (recFuncT x ts) s))
Moreover, the function transmap can also be implemented in general, at least for StateT:
transmap :: Monad m => (forall b. m b -> m b) -> StateT s m a -> StateT s m a
transmap f st = StateT (\s -> f (runStateT st s)
And then we could write recFuncT nicely in terms of it:
recFuncT :: a -> [t] -> StateT m s a
recFuncT x [] = return x
recFuncT x (t:ts) = transmap myFunc (recFuncT x ts)
I realize this does not really match with the code that I included originally, but it does match with the overall principle I was trying to appeal to saying that the StateT transformer is like adding state to my monad m, and therefore anything that can be done at the m (State s a) level can be done at the StateT s m a level.

In a monad transformer, why is the known monad the inner one?

For example, MaybeT is defined as:
newtype MaybeT m a =
MaybeT { runMaybeT :: m (Maybe a)}
But not:
newtype MaybeT m a =
MaybeT { runMaybeT :: Maybe (m a) }
Why is this?
After expanding newtypes, we have join :: Monad m => m (Maybe (m (Maybe a))) -> m (Maybe a) in the first case and join :: Monad m => Maybe (m (Maybe (m a))) -> Maybe (m a) in the second.
To implement the first join you need a way to distribute Maybe over m: dist1 :: Monad m => Maybe (m a) -> m (Maybe a) :
join1 :: m (Maybe (m (Maybe a))) -> m (Maybe a)
join1 = fmap join . join . fmap dist1
To implement the second join you need the opposite distributive law dist2 :: Monad m => m (Maybe a) -> Maybe (m a)
join2 :: Maybe (m (Maybe (m a))) -> Maybe (m a)
join2 = fmap join . join . fmap dist2
dist1 is easy to implement (I'll leave proving the monad transformer laws to you):
dist1 :: Monad m => Maybe (m a) -> m (Maybe a)
dist1 = sequenceA
dist2 is not so easy. It can't be done for an arbitrary Monad. As a counterexample, let's pick m to be the "reader" monad (->) r:
dist2 :: (r -> Maybe a) -> Maybe (r -> a)
Since you don't have access to an r, the only implementation of dist2 that'll typecheck is const Nothing, which clearly won't satisfy the monad laws.
Looking at StateT might be instructive:
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
Here the state is neither "inner" nor "outer", but its type is interleaved with the monad it is transforming, some bits inside, some outside. And indeed
newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
is all "outer". So it depends on what transformer it is. There's probably some category theory that at least partially explains this interleaving, I'm curious to know about it (intelligentsia?).
Contrast with applicative functors, for which
newtype Compose f g a = Compose { getCompose :: f (g a) }
is an applicative as well, so there is always a clear "inner/outer" relationship. You could make an applicative-only StateT, and finding its structure by Compose (State s):
ApplicativeStateT s f a = s -> (s, f a)
In fact, there's another one if you compose on the right:
ApplicativeStateT' s f a = f (s -> (s,a))
But monads have no such regularity.

What is this simple function called?

Have you already seen the following function? What is it called? What is it useful for? can it be defined more generically than just for StateT?
simpleFunction (StateT f) = StateT $ (\s -> return (f s, s))
By the way, ghc gives it the type Monad n => StateT s m a -> StateT s n (m (a, s)).
And there is an alternative definition:
simpleFunction m = do
s <- get
mapStateT (\l -> return (l, s)) m
Having two monads like n (m a) isn't usually very useful (the composition might not be a monad etc.). So I guess more usable version would be of type
(Monad m) => StateT s m a -> StateT s m (a, s).
This can be generalized to an arbitrary state transformer over m:
import Control.Monad
import Control.Monad.State
f1 :: (MonadState s (t m), MonadTrans t, Monad m) => StateT s m a -> t m (a, s)
f1 (StateT f) = get >>= lift . f
And since the only thing we need is get, we can further generalize to:
f2 :: (MonadTrans t, Monad m, Monad (t m)) => t m s -> StateT s m a -> t m (a, s)
f2 g (StateT f) = g >>= lift . f
If you really need to have two monads, perhaps MFunctor would be useful - functions like hoist or generalize allow to switch between monads.
The simpleFunction structure is parameterized over two things: a StateT monad and a function f. As it is shown in both given definitions, the simpleFunction gets the state from the internals of the monad, then map both the return value and final state of a computation using a given function.
Following a very simple example to see a working example:
import Control.Monad.State
inc :: State Int Int
inc = do
n <- get
put (n + 1)
return n
simpleFunction = do
s <- get
mapState (\l -> (l,s)) inc
main = do
print $ runState simpleFunction 1
The result is: ((1,2),1) which is the ((return value,final state),initial state)
The simpleFunction as you see is not complicated. It can be used with monads other than StateT. In this case, you have to implement your own map and get.
Hope it's useful!

Repacking monads -- any generic way?

Given two monads, Monad m and Monad n, I would like to transform m (n a) into n (m a). But there seems to be no generic way because both (>>=) and return deals with only one monad type, and although (>>=) allows extracting content from a monad, you must pack them back to the same monad type so it can be a result value.
However, if we set m to a fixed type, the job becomes easy. Take Maybe as an example:
reorder :: (Monad n) => Maybe (n a) -> n (Maybe a)
reorder Nothing = return Nothing
reorder (Just x) = do
x' <- x
return $ Just x'
Or a list:
reorder :: (Monad n) => [n a] -> n [a]
reorder [] = return []
reorder (x:xs) = do
x' <- x
xs' <- reorder xs
return (x':xs')
Not hard to see, we've got a pattern here. To be more obvious, write it in a Applicative way, and it's no more than applying the data constructor to each element:
reorder (Just x) = Just <$> x
reorder (x:xs) = (:) <$> x <*> (reorder xs)
My question is: does a haskell typeclass already exist to describe such operations, or do I have to invent the wheel myself?
I had a brief search in the GHC documentation, and found nothing useful for this topic.
Data.Traversable provides what you are looking for:
sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
GHC even provides support for automatically deriving instances:
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
import Data.Foldable
import Data.Traversable
data List a = Nil | Cons a (List a)
deriving(Functor, Foldable, Traversable)
A quick search on hoogle for (Monad m, Monad n) => m (n a) -> n (m a) showed me that there are several functions that (roughly) comply with the signature you're looking for:
Data.Traversable.sequence :: (Traversable t, Monad m) => t (m a) -> m (t a);
Data.Traversable.sequenceA :: Applicative f => t (f a) -> f (t a);
Contro.Monad.sequence :: Monad m => [m a] -> m [a] (also exported by Prelude).
Both [a] and Maybe a are instances of traversable, so your reorder functions are just applications of Data.Traversable.sequence. One could write, in example:
ghci> (Data.Traversable.sequence $ Just (return 1)) :: IO (Maybe Int)
Just 1
it :: Maybe Int
ghci> (Data.Traversable.sequence $ Just ([1])) :: [Maybe Int]
[Just 1]
it :: [Maybe Int]
ghci> (Data.Traversable.sequence $ [Just 1]) :: Maybe [Int]
Just [1]
it :: Maybe [Int]
Please note however that the specific class declaration is class (Functor t, Foldable t) => Traversable t, and if you look also at the types of the other two functions, it does not seems like what you're looking for could possibly be done in a generic way for all monads m and n without restrictions/preconditions.
It can't be done in general: a good example of a monad that can't do this is the reader (or function) monad. That would require the following function to be definable:
impossible :: (r -> IO a) -> IO (r -> a)
It's not straightforward to prove that a function cannot be implemented. But intuitively, the problem is that whatever IO has to be done in the value returned has to be done before we know what the r parameter is. So impossible readFile would have to yield a pure function FilePath -> String before it knew which files to open. Clearly, at least, impossible can't do what you'd want it to.
Not all Monads can commute in that way. Edward Kmett's distributive package provides a typeclass Distributive for type constructors that is similar to what you desire (simplified):
class Functor g => Distributive g where
distribute :: Functor f => f (g a) -> g (f a)
collect :: Functor f => (a -> g b) -> f a -> g (f b)
Default definitions are provided for distribute and collect, written in terms of each other. I found this package by searching hayoo for the desired type signature.

Resources