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.
Related
I wonder whether there is a good name for functions with the following signature and implementation (Haskell-notation):
humble :: (a -> a -> b) -> a -> b
humble f x = f x x
It seems somehow related to fold1 (fold with no base case).
As has been mentioned by #4castle in the comments, the function you're looking for is join in Control.Monad. It's type is
join :: Monad m => m (m a) -> m a
The simple reader monad is (->) r,so if we set m ~ (->) r, we get
join :: (->) r ((->) r a) -> (->) r a
or, more concisely,
join :: (r -> r -> a) -> (r -> a)
which is what you want.
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
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.
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.
I would like to implement a function, iterateM, whose type would look like this:
iterateM :: Monad m => (a -> m a) -> a -> [m a]
However, my first go at writing this function:
iterateM f x = f x >>= (\x' -> return x' : iterateM f x')
Gives me the error:
Could not deduce (m ~ [])
from the context (Monad m)
bound by the type signature for
iterateM :: Monad m => (a -> m a) -> a -> [m a]
at main.hs:3:1-57
`m' is a rigid type variable bound by
the type signature for
iterateM :: Monad m => (a -> m a) -> a -> [m a]
at main.hs:3:1
Expected type: [a]
Actual type: m a
In the return type of a call of `f'
In the first argument of `(>>=)', namely `f x'
In the expression: f x >>= (\ x' -> return x' : iterateM f x')
If I remove my type-signature, ghci tells me the type of my function is:
iterateM :: Monad m => (a -> [a]) -> a -> [m a]
What am I missing here?
What I gather from your signature:
iterateM :: (Monad m) => (a -> m a) -> a -> [m a]
Is that the nth element iterateM f x will be an action that runs f n times. This is very close to iterate, I suspect we can implement it in terms of that.
iterate :: (b -> b) -> b -> [b]
iterate gives us a list of bs, and we want a list of m as, so I suspect b = m a.
iterate :: (m a -> m a) -> m a -> [m a]
Now we need a way to transform f :: a -> m a into something of type m a -> m a. Fortunately, that is exactly the definition of bind:
(=<<) :: (Monad m) => (a -> m b) -> (m a -> m b)
So:
\f -> iterate (f =<<) :: (a -> m a) -> m a -> [m a]
And to get our initial x :: a into the desired m a, we can use return:
return :: (Monad m) => a -> m a
So:
iterateM f x = iterate (f =<<) (return x)
Pointfreeize to taste.
Your recursive use of iterateM is forcing it to be in the list monad. You need to run the iterateM action and return its result.
Try:
iterateM f x = do
x' <- f x
xs <- iterateM f x'
return $ x':xs