# Exercise solutions

## Exercise 1

Try implementing `liftA2` for `Maybe`.

The type looks like this.

``````liftA2 @Maybe :: (a -> b -> c) ->
Maybe a -> Maybe b -> Maybe c``````

As we said, it’s very close to `fmap` which you have implemented before. We’ll call the function argument `f`, but you might have called it something else.

``````liftA2 @Maybe :: (a -> b -> c) ->
Maybe a -> Maybe b -> Maybe c
liftA2 f _ Nothing = Nothing
liftA2 f Nothing _ = Nothing
liftA2 f (Just x) (Just y) = Just (f x y)``````

Here’s another flavor – semantically the same, syntactically different.

``````liftCase :: (a -> b -> c) ->
Maybe a -> Maybe b -> Maybe c
liftCase f x y =
case x of
Nothing -> Nothing
Just x ->
case y of
Nothing -> Nothing
Just y -> Just (f x y)``````

You could, of course, write a little property test to make sure that it’s behaving the same as `liftA2 @Maybe` from `base`, but that’s probably not necessary.

## Exercise 2

Given the similarities with `Functor`, see if you can write an `instance` of `Applicative` for `Either`. You can implement either `(<*>)` or `liftA2` or both. You may want to un-import `Either` and its constructors from `Prelude`. You’ll need to have a `Functor` instance in scope for `Either`.

Remember you have a choice of implementing the tie-fighter or `liftA2` for your instance, but you must have `pure` either way. We’ve used the `Either` names for our instances here (un-importing them from `Prelude`).

The types of the `(<*>)` and `liftA2` as specialized to `Either a` are as follows:

``````λ> :type (<*>) @(Either _)
(<*>) @(Either _)
:: Either w (a -> b) -> Either w a -> Either w b

λ> :type liftA2 @(Either _)
liftA2 @(Either _)
:: (a -> b -> c) ->
Either w a -> Either w b -> Either w c``````

`Left` values, which contain the `w`, are treated the same as `Nothing` in the `Maybe` instances.

``````instance Applicative (Either a) where
pure = Right
Left x <*> _ = Left x
_ <*> Left y = Left y
Right f <*> Right y = Right (f y)``````

Alternatively:

``````instance Applicative (Either a) where
pure = Right
liftA2 f (Left x) _ = Left x
liftA2 f _ (Left y) = Left y
liftA2 f (Right x) (Right y) = Right (f x y)``````

You should be noticing a pattern at this point, not just with these but a commonality with the structure of `Functor` instances, too. There is usually only one sensible implementation for a given type For `Functor` there is only ever one sensible implementation, or so we’re told – we’ve never proven this ourselves. Therefore, there is a language extension you can use to derive `Functor` instances, much as you derive `Show` and others. For now, we’d encourage you to keep writing instances by hand as long as you can stand it. The day you find yourself thinking how trivial it is to write this next `Functor` instance, it’s probably safe to start deriving them., and you just do the simplest thing. Part of the reason we have you write so many instances – and you should be writing even more! – is because doing these until they are mechanical because you’ve internalized the pattern is the best way we know to make these patterns really useful to you.