Reputation: 123
I'm working my way through 20 Intermediate Haskell exercises and I got stuck on exercise 13:
-- Exercise 13
-- Relative Difficulty: 6
apple :: (Misty m) => m a -> m (a -> b) -> m b
apple = error "todo"
where the Misty Typeclass is essentially the Monad Typeclass and is implemented like this:
class Misty m where
banana :: (a -> m b) -> m a -> m b
unicorn :: a -> m a
I gave in to my curiosity and found the solution to this exercise online as
apple = banana . flip furry'
where furry' is a version of liftM implemented as
furry' f mi = banana (\x -> unicorn (f x)) mi
What I don't understand is the use of function composition (.) on two binary functions (namely banana and the flipped furry'), if someone could walk through the evaluation of this I think that would help me a lot.
Upvotes: 2
Views: 299
Reputation: 48644
Let's start step by step. Misty
typeclass is given:
class Misty m where
banana :: (a -> m b) -> m a -> m b
unicorn :: a -> m a
Also furry'
is already solved in an earlier problem in those exercises:
furry' :: Misty m => (a -> b) -> m a -> m b
furry' f mi = banana (\x -> unicorn (f x)) mi
Now you have apple
function which you have to define:
apple :: (Misty m) => m a -> m (a -> b) -> m b
apple = error "todo"
Now just try to follow the type signature. Assume you are defining apple
like this:
apple xs ys
xs will have type of m a
ys will have type of m (a -> b)
Now can you see the relation between the above types and furry'
? So
you have to somehow apply xs
and ys
to furry'
Now since it's
second parameter is m a
which you already have in xs
, you can use
flip
to obtain it:
flip furry' :: m a -> (a -> b) -> m b
So you can apply xs
to the first parameter of it and you will have
the following type signature:
(flip furry') xs :: (a -> b) -> m b
------- Equation 1
Any guess on how to apply it ys
? Try to unify the above type
signature with the first parameter of banana
:
That will give you:
a ~ (a -> b)
m b ~ (m b)
So, the type signature of banana
gets transformed from
banana :: (a -> m b) -> m a -> m b
to
banana :: ((a -> b) -> m b) -> m (a -> b) -> m b
Now from Equation (1)
we know that (flip furry') xs
type signature matches
the first parameter of banana
and ys
matches the second parameter
of banana
. And that gives you the definition of apple
:
apple :: (Misty m) => m a -> m (a -> b) -> m b
apple xs ys = banana ((flip furry') xs ) ys
which can be expressed in pointfree manner as:
apple :: (Misty m) => m a -> m (a -> b) -> m b
apple = banana . flip furry'
Upvotes: 4