Defining Monad Operators - haskell

In Haskell's Monads, I can easily define the operator (>=>) as :
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
f >=> g = \x -> f x >>= g
I also know that (>>=) can be expressed using (>=>): Let's call (>>=) as (..):
(..) :: Monad m => m a -> (a -> m b) -> m b
m .. k = m >=> \_ -> k
However something is not right ... could someone point what?

The idea of using a constant function (that is, \_ -> -- etc.) to make a function out of the argument which isn't a function so that you can pass it to (>=>) is sound. There are just two issues. Firstly, you are doing it to the wrong argument, as the one which isn't a function is m:
GHCi> :t \m k -> (\_ -> m) >=> k
\m k -> (\_ -> m) >=> k :: Monad m => m b -> (b -> m c) -> a -> m c
Secondly, (>=>) gives you a function (of type a -> m c in the demo just above). You have to apply it to something to get a result type that matches the one of (>>=). As that argument is irrelevant (you are ultimately feeding it to a constant function) you can just use ():
GHCi> :t \m k -> ((\_ -> m) >=> k) ()
\m k -> ((\_ -> m) >=> k) () :: Monad m => m b -> (b -> m c) -> m c
And that's it. I find it slightly prettier to use the const function rather than writing \_ ->, and so I would write it as:
(>>..) :: Monad m => m a -> (a -> m b) -> m b
m >>.. k = (const m >=> k) ()

The solution is the following:
(..) :: Monad m => m a -> (a -> m b) -> m b
m .. k =
(const m >=> k) undefined
Using const we're lifting an operation of type m a to whatever -> m a. This lifted version does not give a damn, what we pass to it so it might as well be the undefined.

Related

Haskell writing >>= using >=> Monads

(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
bind :: Monad m => m a -> (a -> m b) -> m b
-- how do you use >=> to write bind?
I am absolutely so confused, I understand how both of these works but I cant even get started.
I tried all the following alternatives:
bind1 a b = (b a)
bind2 a b = (a >=> b)
bind3 a b = (b >=> a)
bind4 a b = (a b)
but every single attempt raises an error. Where can i possibly start on this question?
Since >>= has 2 parameters, and >=> has 3, how can I use >=> to write >>= when there is 1 less parameter?
First I'd suggest renaming the type parameters so the final result matches:
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
bind :: Monad m => m a -> (a -> m c) -> m c
Now we have a b -> m c in the first signature and a -> m c in the second; that suggests renaming also a to b:
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
bind :: Monad m => m b -> (b -> m c) -> m c
That leaves the main difference as having an extra argument a. But we evidently don't need that, so we might as well specialize it to the information-less type () (or any other single-value type):
(>=>) :: Monad m => (() -> m b) -> (b -> m c) -> (() -> m c)
bind :: Monad m => m b -> (b -> m c) -> m c
() -> m x is actually isomorphic to m x alone:
addDummyArg :: a -> (() -> a)
addDummyArg c () = c
rmDummyArg :: (() -> a) -> a
rmDummyArg f = f ()
And it's just a matter of using those conversion functions to adapt the functions to each other.
Since >>= has 2 parameters, and >=> has 3, how can I use >=> to write >>= when there is 1 less parameter?
Each function in Haskell has one parameter. You can interpret >=> , as a function that has as first parameter something of type a -> m b and the second something of b -> m c, the a -> m c is the "result" function.
What you here can do is manipulate the first parameter of bind into a function that accepts a parameter, and then provide that parameter, something like:
bind :: Monad m => m a -> (a -> m b) -> m b
bind ma f = (const ma >=> f) undefined
Here with const ma, we thus create a function that takes a parameter we do not care about, then we construct an a -> m c by using >=> and we call it with undefined (or some other value) to produce the m c value.

Haskell - is there extended monad type [ m (a -> m b) -> m a -> m b ]

Functor has
(a -> b) -> m a -> m b
Applicative has
f (a -> b) -> f a -> f b
Monad has
m a -> (a -> m b) -> m b
But, Is there extended monad type that has
m a -> m (a -> m b) -> m b
or
m (a -> m b) -> m a -> m b
?
A Monad constraint is sufficient to implement a (sensible) function with that type signature:
foo :: Monad m => m (a -> m b) -> m a -> m b
foo mf ma = do
f <- mf
a <- ma
f a
or, if you prefer:
foo' :: Monad m => m (a -> m b) -> m a -> m b
foo' mf ma = mf >>= \f -> ma >>= f
This means that your proposed operation, even though it looks like a generalization of the usual >>= bind operation, isn't actually a generalization. Any >>= operation can be written in terms of foo, and any foo operation can be written in terms of >>=, so they are operations of equivalent "power".
In contrast, the other operations are not of equivalent power. Any applicative operation <*> can be written in terms of >>= and return, but you can't in general implement >>= in terms of <*>, so >>= is a strictly more powerful operation, etc.

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.

Haskell operator or function for applying function from monad to a value?

I'm looking for a function or operator in Haskell that is effectively a Monad equivalent of the Applicative operator <*> that applies a monadic action rather than a bare function, that is instead of this:
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
I'm looking for something that looks like this:
... :: Monad m => m (a -> m b) -> m a -> m b
I can't believe that this isn't a standard function, but I can't see anything that matches. Am I missing something?
This will be a simple composition of two other basic monad functions, namely join and ap; since:
ap :: Monad m => m (a -> b) -> m a -> m b
join :: Monad m => m (m a) -> m a
we get:
(join .) . ap :: Monad m => m (a -> m b) -> m a -> m b
as well as:
(join .) . (<*>) :: Monad m => m (a -> m b) -> m a -> m b
or, using only bind operator, another construct would be:
(. (>>=)) . (>>=) :: Monad m => m (a -> m b) -> m a -> m b

Implementing Applicative's (<*>) for Monad

Applicative's has the (<*>) function:
(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
Learn You a Haskell shows the following function.
Given:
ap :: (Monad m) => m (a -> b) -> m a -> m b
ap f m = do
g <- f -- '<-' extracts f's (a -> b) from m (a -> b)
m2 <- m -- '<-' extracts a from m a
return (g m2) -- g m2 has type `b` and return makes it a Monad
How could ap be written with bind alone, i.e. >>=?
I'm not sure how to extract the (a -> b) from m (a -> b). Perhaps once I understand how <- works in do notation, I'll understand the answer to my above question.
How could ap be written with bind alone, i.e. >>= ?
This is one sample implementation I can come up with:
ap :: (Monad m) => m (a -> b) -> m a -> m b
ap xs a = xs >>= (\f -> liftM f a)
Of if you don't want to even use liftM then:
ap :: (Monad m) => m (a -> b) -> m a -> m b
ap mf ma = mf >>= (\f -> ma >>= (\a' -> return $ f a'))
Intially these are the types:
mf :: m (a -> b)
ma :: m a
Now, when you apply bind (>>=) operator to mf: mf >>= (\f-> ..., then f has the type of:
f :: (a -> b)
In the next step, ma is also applied with >>=: ma >>= (\a'-> ..., here a' has the type of:
a' :: a
So, now when you apply f a', you get the type b from that because:
f :: (a -> b)
a' :: a
f a' :: b
And you apply return over f a' which will wrap it with the monadic layer and hence the final type you get will be:
return (f a') :: m b
And hence everything typechecks.

Resources