Lesson 9: The four laws of Applicative
We had a short introduction to one of the
Applicative class laws in the previous lesson. But the
Applicative class has a lot of laws – four or five, depending on whether you count the law that relates it to
fmap – so there is still a lot to cover here. The identity and composition laws are similar to the laws of the same names for both
Bifunctor, and, as mentioned, there is also a law that ensures that an
Applicative instance is coherent with the
Functor instance. This typeclass also has two laws that don’t have analogues in any typeclass we’ve talked about so far. The names of these laws, the homomorphism law and the interchange law, may seem very opaque, but looking at examples will make the intent of the laws clear, even if the names are not so clear.
Furthermore, there should be a coherence with the
Functor instance that superclasses the
Applicative so the interaction of
fmap and applicatives should be predictable – this is further ensured by the orthogonality of the monoidal and function application bits of the applicative, because
fmap was also denied the ability to affect the “structure” or context of the function application in any way. So, despite their names and complicated looking implementations, we can make sense of their meaning and utility.
As we discuss each law, we’ll be using the property testing library
hedgehog to ensure we write good, useful, law-abiding
The gist of the laws, considered together, is that
Applicative has two components: pure function application and a monoidal “effects” layer and these are independent of each other. The effects layer and the function application layer don’t interact and can’t influence the results of the other; an “effect” such as
Nothing can mean there is no function application to do, but it can’t change the results of the function application itself.