Haskell monad into monad - haskell

There are method (>>=) :: forall a b. m a -> (a -> m b) -> m b.
How can i make method :: forall a b. m (n a) -> (a -> m (n b)) -> m (n b) where m and n is monads.

As PyRulez writes, there's no general solution for this, but given the types you report, something like the following should work.
You're going to need
import Control.Monad (join)
Using do notation, you can compose two functions, foo and bar, like this:
comp :: (a -> TargetClient (MethodResult b)) ->
(b -> TargetClient (MethodResult c)) ->
a -> TargetClient (MethodResult c)
comp foo bar x = do
f <- foo x
b <- join <$> traverse bar f
return b
If you don't like the do notation, you can reduce it all to this:
comp' :: (a -> TargetClient (MethodResult b)) ->
(b -> TargetClient (MethodResult c)) ->
a -> TargetClient (MethodResult c)
comp' foo bar x = foo x >>= fmap join . traverse bar
When you map f with bar, you'll get the monads stacked in the wrong order, so to speak, but you can use traverse to switch the stack. Even when you do that, you'll have an Either in an Either, so that's the reason you need join.

If both m and n are monads, you need an additional piece to make the composite m.n a monad as well.
What is required is a "distributive law", that is a natural morphism
forall a . n(m a) -> m(n a) (see here it comes from Beck and is also used in Street)
It then becomes easy to write the missing piece and verify it satisfies the monad laws.

Related

Why can function composition with `join` change function inputs?

I have recently started learning Haskell, and I was trying to do the following function composition (join . mapM) but got some weird types out of this function that I don't understand. I thought that either GHC would assume that t == m in the mapM type and the output of mapM would become m (m b) which would be join-able or it would not and this would error out because of type mismatch. Instead the following happened:
mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
join :: Monad m => m (m a) -> m a
join . mapM :: Traversable t => (a -> t a -> b) -> t a -> t b
I don't understand how this is possible. The way I understand it, function composition should use the inputs of the first (or the second depending how you look at it) function and the outputs of the second function. But here the expected input function for mapM changes from a unary function to a binary function and I have no clue why. Even if GHC can't just make the assumption that t == m like I did, which I half expected, it should error out because of type mismatch, not change the input function type, right? What is happening here?
First you specialize mapM to:
mapM' :: Traversable t => (a -> x -> b) -> t a -> x -> t b
(since (->) x is a monad)
Then you specialize it further to:
mapM'' :: Traversable t => (a -> t a -> b) -> t a -> t a -> t b
(we're just fixing the x to be t a)
Finally we specialize join appropriately:
join' :: (x -> x -> r) -> x -> r
(again, (->) x is a monad)
And hopefully it becomes more apparent why the composition join' . mapM'' is
join' . mapM'' :: Traversable t => (a -> t a -> b) -> t a -> t b
Maybe the following will be more illuminating, instead :
flip mapT :: (Traversable t, Monad m) => t a -> (a -> m b) -> t (m b)
sequenceA :: (Traversable t, Monad m) => t (m b) -> m (t b)
flip mapM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)
flip liftM :: Monad m => m a -> (a -> m b) -> m (m b)
join :: Monad m => m (m b) -> m b
(join .) . flip liftM :: Monad m => m a -> (a -> m b) -> m b
(>>=) :: Monad m => m a -> (a -> m b) -> m b
(using some more specialized types than the most general ones, here and there; also with the renamed mapT f = runIdentity . traverse (Identity . f)).
Your specific question is less interesting. Type derivation is a fully mechanical process. Some entities must be compatible for the whole expression to make sense, so their types must unify:
(join . mapM) a_mb x = -- a_mb :: a -> m b
= join (mapM a_mb) x
= join ta_mtb x -- ta_mtb :: t a -> m (t b)
To join a function is to call it twice,
= ta_mtb x x
which means x is a t a and so m is t a ->:
x :: t a
ta_mtb :: t a -> m (t b)
----------------------------
ta_mtb x :: m (t b)
~ t a -> t b
x :: t a
----------------------------
ta_mtb x x :: t b
thus a_mb :: a -> m b ~ a -> t a -> b.

foldlWithKey in monad

I'm looking for a function that like foldlWithKey, but encapsulated in a monad.
I would expect it to have type
Monad m => (a -> k -> b -> m a) -> a -> Map k b -> m a
but Hoogle isn't giving me anything with that type.
foldlWithKey is already very close to what you want. If you specialize a to m a you will have something that operates on values encapsulated in a monad.
foldlWithKey :: ( a -> k -> b -> a) -> a -> Map k b -> a
foldlWithKey :: (m a -> k -> b -> m a) -> m a -> Map k b -> m a
{- ^- you don't want these -^ -}
We can get rid of the two m as you don't want with >>= and return.
foldlWithKeyM :: Monad m => (a -> k -> b -> m a) -> a -> Map k b -> m a
foldlWithKeyM f acc = foldlWithKey f' (return acc)
where
f' ma k b = ma >>= \a -> f a k b
#Cirdec's solution certainly works, but it has a possible problem: It nests >>=s deeply leftwards. For many (but not all!) monads, this can give stack blowup similar to when using non-strict foldl. So I'll present a different solution, which nests >>=s rightwards instead. For monads such as IO this should allow the action to be constructed and consumed lazily from the map as it is executed.
This solution is probably a bit trickier, as it uses a right fold to build up the monadic function that will eventually consume the starting value. At least I had some trouble getting the types right.
Except for the key handling, this is essentially the same method as used by Data.Foldable.foldlM.
-- Pragma needed only to give f' a type signature for sanity. Getting it
-- right almost took a piece of mine until I remembered typed holes.
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Map
foldlWithKeyM
:: forall m a k b. Monad m => (a -> k -> b -> m a) -> a -> Map k b -> m a
foldlWithKeyM f start m = foldrWithKey f' return m $ start
where
f' :: k -> b -> (a -> m a) -> (a -> m a)
f' k b a2mb a = f a k b >>= a2mb

Understanding "Monad m" in >>=

Looking at Haskell's bind:
Prelude> :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
I was confused by the following example:
Prelude> let same x = x
Prelude> [[1]] >>= \x -> same x
[1]
Looking at >>='s signature, how does \x -> same x type check with a -> m b?
I would've expected \x -> same x to have produced a [b] type, since the Monad m type here is [], as I understand.
You say
I would've expected \x -> same x to have produced a [b] type, since the Monad m type here is [], as I understand.
and so it does because it is.
We have
[[1]] >>= \ x -> same x
=
[[1]] >>= \ x -> x
[[Int]] [Int] -> [Int] :: [Int]
[] [Int] [Int] -> [] Int :: [] Int
m a a m b m b
Sometimes [] is describing a kind of "nondeterminism" effect. Other times, [] is describing a container-like data structure. The fact that it's difficult to tell the difference between which of these two purposes is being served is a feature of which some people are terribly proud. I'm not ready to agree with them, but I see what they're doing.
Looking at >>='s signature, how does \x -> same x type check with a -> m b?
It's actually very simple. Look at the type signatures:
same :: x -> x
(>>=) :: Monad m => m a -> (a -> m b) -> m b
(>>= same) :: Monad m => m a -> (a -> m b) -> m b
|________|
|
x -> x
Therefore:
x := a
-- and
x := m b
-- and by transitivity
a := x := m b
-- or
a := m b
Hence:
(>>= same) :: Monad m => m (m b) -> m b
This is just the join function from the Control.Monad module, and for the list monad it is the same as the concat function. Thus:
[[1]] >>= \x -> same x
-- is the same as the following via eta reduction
[[1]] >>= same
-- is the same as
(>>= same) [[1]]
-- is the same as
join [[1]]
-- is the same as
concat [[1]]
-- evaluates to
[1]
I would've expected \x -> same x to have produced a [b] type, since the Monad m type here is [], as I understand.
Indeed, it does. The \x -> same x function which has the type x -> x is specialized to the type [b] -> [b] as I explained above. Hence, (>>= same) is of the type [[b]] -> [b] which is the same as the concat function. It flattens a list of lists.
The concat function is a specialization of the join function which flattens a nested monad.
It should be noted that a monad can be defined in terms of either >>= or fmap and join. To quote Wikipedia:
Although Haskell defines monads in terms of the return and >>= functions, it is also possible to define a monad in terms of return and two other operations, join and fmap. This formulation fits more closely with the original definition of monads in category theory. The fmap operation, with type Monad m => (a -> b) -> m a -> m b, takes a function between two types and produces a function that does the “same thing” to values in the monad. The join operation, with type Monad m => m (m a) -> m a, “flattens” two layers of monadic information into one.
The two formulations are related as follows:
fmap f m = m >>= (return . f)
join n = n >>= id
m >>= g ≡ join (fmap g m)
Here, m has the type Monad m => m a, n has the type Monad m => m (m a), f has the type a -> b, and g has the type Monad m => a -> m b, where a and b are underlying types.
The fmap function is defined for any functor in the category of types and functions, not just for monads. It is expected to satisfy the functor laws:
fmap id ≡ id
fmap (f . g) ≡ (fmap f) . (fmap g)
The return function characterizes pointed functors in the same category, by accounting for the ability to “lift” values into the functor. It should satisfy the following law:
return . f ≡ fmap f . return
In addition, the join function characterizes monads:
join . fmap join ≡ join . join
join . fmap return ≡ join . return = id
join . fmap (fmap f) ≡ fmap f . join
Hope that helps.
As a few people have commented, you've found a really cute property about monads here. For reference, let's look at the signature for bind:
:: Monad m => m a -> (a -> m b) -> m b
In your case, the type a === m b as you have a [[a]] or m (m a). So, if you rewrite the signature of the above bind operation, you get:
:: Monad m => m (m b) -> ((m b) -> m b) -> m b
I mentioned that this is cute, because by extension, this works for any nested monad. e.g.
:: [[b]] -> ([b] -> [b]) -> [b]
:: Maybe (Maybe b) -> (Maybe b -> Maybe b) -> Maybe b
:: Reader (Reader b) -> (Reader b -> Reader b) -> Reader b
If you look at the function that get's applied here, you'll see that it's the identity function (e.g. id, same, :: forall a. a -> a).
This is included in the standard libraries for Haskell, as join. You can look at the source here on hackage. You'll see it's implemented as bind id, or \mma -> mma >>= id, or (=<<) id
As you say m is []. Then a is [Integer] (ignoring the fact that numbers are polymorphic for simplicity's sake) and b is Integer. So a -> m b becomes [Integer] -> [Integer].
First: we should use the standard version of same, it is called id.
Now, let's rename some type variables
id :: (a'' ~ a) => a -> a''
What this means is: the signature of id is that of a function mapping between two types, with the extra constraint that both types be equal. That's all – we do not require any particular properties, like “being flat”.
Why the hell would I write it this way? Well, if we also rename some of the variables in the bind signature...
(>>=) :: (Monad m, a'~m a, a''~m b) => a' -> (a -> a'') -> a''
...then it is obvious how we can plug the id, as the type variables have already been named accordingly. The type-equality constraint a''~a from id is simply taken to the compound's signature, i.e.
(>>=id) :: (Monad m, a'~m a, a''~m b, a''~a) => a' -> a''
or, simplifying that,
(>>=id) :: (Monad m, a'~m a, m b~a) => a' -> m b
(>>=id) :: (Monad m, a'~m (m b)) => a' -> m b
(>>=id) :: (Monad m) => m (m b) -> m b
So what this does is, it flattens a nested monad to a single application of that same monad. Quite simple, and as a matter of fact this is one the “more fundamental” operation: mathematicians don't define the bind operator, they instead define two morphisms η :: a -> m a (we know that, it's return) and μ :: m (m a) -> m a – yup, that's the one you've just discovered. In Haskell, it's called join.
The monad here is [a] and the example is pointlessly complicated. This’ll be clearer:
Prelude> [[1]] >>= id
[1]
just as
Prelude> [[1]] >>= const [2]
[2]
i.e. >>= is concatMap and is concat when used with id.

Why does Djinn fail to realize common monadic functions?

I recently stumbled across Djinn and was briefly playing around with it to try to see whether it would be useful in my everyday coding workflow. I was excited to see that Djinn had monads and tried to see whether it might be able to find some cool functions.
Djinn did in fact work some wonders. The type signature of the initially (at least to me) unintuitive function >>= (>>=) is Monad m => ((a -> m b) -> m a) -> (a -> m b) -> m b. Djinn was able to immediately demystify this by stating
Djinn> f ? Monad m => ((a -> m b) -> m a) -> (a -> m b) -> m b
f :: (Monad m) => ((a -> m b) -> m a) -> (a -> m b) -> m b
f a b = a b >>= b
Unfortunately, Djinn can't seem to find other standard functions on monads, despite knowing about the Monad typeclass.
join (which should be join = (>>= id) or in Djinn's more verbose syntax join a = a >>= (\x -> x))
Djinn> join ? Monad m => m (m a) -> m a
-- join cannot be realized.
liftM (which should be liftM f = (>>= (return . f)) or in Djinn's more verbose syntax liftM a b = b >>= (\x -> return (a x)))
Djinn> liftM ? Monad m => (a -> b) -> m a -> m b
-- liftM cannot be realized.
Even the basic return :: Monad m => m a -> m (m a) cannot be found by Djinn or return :: Monad m => (a, b) -> m (a, b).
Djinn> f ? Monad m => (a, b) -> m (a, b)
-- f cannot be realized.
Djinn knows how to use \ to construct anonymous functions so why is this the case?
My rough suspicion is that perhaps Djinn has a simplistic notion of typeclass and somehow treats m a as "fixed" so that m (a, b) is not seen as a case of m a, but I have no idea how to make that any more concrete than its current hand-wavy form or whether that intuition is correct.
Supporting type classes properly looks a lot like supporting rank-2 types; compare:
join :: Monad m
=> m (m a) -> m a
vs:
join :: (forall a. a -> m a)
-> (forall a b. m a -> (a -> m b) -> m b)
-> m (m a) -> m a
Unfortunately, the techniques Djinn uses don't handle rank-2 types at all. If you float the foralls so that Djinn can process it, suddenly what you get instead are concrete choices:
join :: (b -> m b)
-> (m c -> (c -> m d) -> m d)
-> m (m a) -> m a
which looks a lot less like you could implement it! If you tell Djinn which instantiations to use, it does a lot better, of course.
join :: (b -> m b)
-> (m (m a) -> (m a -> m a) -> m a)
-> m (m a) -> m a
For this one, Djinn will give the right implementation. ...but then, that's cheating.

Why use such a peculiar function type in monads?

New to Haskell, and am trying to figure out this Monad thing. The monadic bind operator -- >>= -- has a very peculiar type signature:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
To simplify, let's substitute Maybe for m:
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
However, note that the definition could have been written in three different ways:
(>>=) :: Maybe a -> (Maybe a -> Maybe b) -> Maybe b
(>>=) :: Maybe a -> ( a -> Maybe b) -> Maybe b
(>>=) :: Maybe a -> ( a -> b) -> Maybe b
Of the three the one in the centre is the most asymmetric. However, I understand that the first one is kinda meaningless if we want to avoid (what LYAH calls boilerplate code). However, of the next two, I would prefer the last one. For Maybe, this would look like:
When this is defined as:
(>>=) :: Maybe a -> (a -> b) -> Maybe b
instance Monad Maybe where
Nothing >>= f = Nothing
(Just x) >>= f = return $ f x
Here, a -> b is an ordinary function. Also, I don't immediately see anything unsafe, because Nothing catches the exception before the function application, so the a -> b function will not be called unless a Just a is obtained.
So maybe there is something that isn't apparent to me which has caused the (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b definition to be preferred over the much simpler (>>=) :: Maybe a -> (a -> b) -> Maybe b definition? Is there some inherent problem associated with the (what I think is a) simpler definition?
It's much more symmetric if you think in terms the following derived function (from Control.Monad):
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
(f >=> g) x = f x >>= g
The reason this function is significant is that it obeys three useful equations:
-- Associativity
(f >=> g) >=> h = f >=> (g >=> h)
-- Left identity
return >=> f = f
-- Right identity
f >=> return = f
These are category laws and if you translate them to use (>>=) instead of (>=>), you get the three monad laws:
(m >>= g) >>= h = m >>= \x -> (g x >>= h)
return x >>= f = f x
m >>= return = m
So it's really not (>>=) that is the elegant operator but rather (>=>) is the symmetric operator you are looking for. However, the reason we usually think in terms of (>>=) is because that is what do notation desugars to.
Let us consider one of the common uses of the Maybe monad: handling errors. Say I wanted to divide two numbers safely. I could write this function:
safeDiv :: Int -> Int -> Maybe Int
safeDiv _ 0 = Nothing
safeDiv n d = n `div` d
Then with the standard Maybe monad, I could do something like this:
foo :: Int -> Int -> Maybe Int
foo a b = do
c <- safeDiv 1000 b
d <- safeDiv a c -- These last two lines could be combined.
return d -- I am not doing so for clarity.
Note that at each step, safeDiv can fail, but at both steps, safeDiv takes Ints, not Maybe Ints. If >>= had this signature:
(>>=) :: Maybe a -> (a -> b) -> Maybe b
You could compose functions together, then give it either a Nothing or a Just, and either it would unwrap the Just, go through the whole pipeline, and re-wrap it in Just, or it would just pass the Nothing through essentially untouched. That might be useful, but it's not a monad. For it to be of any use, we have to be able to fail in the middle, and that's what this signature gives us:
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
By the way, something with the signature you devised does exist:
flip fmap :: Maybe a -> (a -> b) -> Maybe b
The more complicated function with a -> Maybe b is the more generic and more useful one and can be used to implement the simple one. That doesn't work the other way around.
You can build a a -> Maybe b function from a function f :: a -> b:
f' :: a -> Maybe b
f' x = Just (f x)
Or, in terms of return (which is Just for Maybe):
f' = return . f
The other way around is not necessarily possible. If you have a function g :: a -> Maybe b and want to use it with the "simple" bind, you would have to convert it into a function a -> b first. But this doesn't usually work, because g might return Nothing where the a -> b function needs to return a b value.
So generally the "simple" bind can be implemented in terms of the "complicated" one, but not the other way around. Additionally, the complicated bind is often useful and not having it would make many things impossible. So by using the more generic bind monads are applicable to more situations.
The problem with the alternative type signature for (>>=) is that it only accidently works for the Maybe monad, if you try it out with another monad (i.e. List monad) you'll see it breaks down at the type of b for the general case. The signature you provided doesn't describe a monadic bind and the monad laws can't don't hold with that definition.
import Prelude hiding (Monad, return)
-- assume monad was defined like this
class Monad m where
(>>=) :: m a -> (a -> b) -> m b
return :: a -> m a
instance Monad Maybe where
Nothing >>= f = Nothing
(Just x) >>= f = return $ f x
instance Monad [] where
m >>= f = concat (map f m)
return x = [x]
Fails with the type error:
Couldn't match type `b' with `[b]'
`b' is a rigid type variable bound by
the type signature for >>= :: [a] -> (a -> b) -> [b]
at monadfail.hs:12:3
Expected type: a -> [b]
Actual type: a -> b
In the first argument of `map', namely `f'
In the first argument of `concat', namely `(map f m)'
In the expression: concat (map f m)
The thing that makes a monad a monad is how 'join' works. Recall that join has the type:
join :: m (m a) -> m a
What 'join' does is "interpret" a monad action that returns a monad action in terms of a monad action. So, you can think of it peeling away a layer of the monad (or better yet, pulling the stuff in the inner layer out into the outer layer). This means that the 'm''s form a "stack", in the sense of a "call stack". Each 'm' represents a context, and 'join' lets us join contexts together, in order.
So, what does this have to do with bind? Recall:
(>>=) :: m a -> (a -> m b) -> m b
And now consider that for f :: a -> m b, and ma :: m a:
fmap f ma :: m (m b)
That is, the result of applying f directly to the a in ma is an (m (m b)). We can apply join to this, to get an m b. In short,
ma >>= f = join (fmap f ma)

Resources