Exercise solution: liftA3, liftA4

It’s handy that Applicative gives us the choice between liftA2 and (<*>), and since the two functions are so closely related, it’s straightforward for the compiler to be able to derive one from the other. We saw how liftA2 is like an fmap for functions with two arguments instead of one.

fmap   :: Functor f =>     (a -> b)      -> f a -> f b

liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c

The only reasonable thing to do, when confronted with this information, is ask oneself: why not liftA3 then? Or liftA4?

liftA3, at least, is something that exists in the Control.Applicative module of base (though, like liftA2, it’s not in Prelude). Try implementing it for yourself – no peeking at the source code! If you feel especially ambitious, try implementing a liftA4 as well, which is not in base but that need not stop us from chasing our dreams. Use what you know about fmap and the relationship of liftA2 to (<*>) to help you.

Sign up for access to the full page, plus the complete archive and all the latest content.