Lesson 4: Zippy applicatives
- Two list monoids?
- Two list applicatives!
- Notes on emptiness
- Exercise 1
- Exercise 2
- Coming up
The previous two lessons have each touched on the monoidal nature of applicative functors. Lesson 9 examined the tuple applicative and its connection to monoids, and in Lesson 10 we saw the connection between monoids and effect sequencing. At the risk of beating a dead horse, we’re going to spend a little more time with it in this lesson, in which we look at lists.
We’ve been avoiding talking about lists in this course, because we believe it’s helpful to understand functors without having to also worry about some of the funkiness that goes along with lists. However, the list applicatives – that’s right: plural – deserve some attention at this time.
We do not typically think of types having more than one valid
Applicative instance. The connection between a type and a typeclass, expressed in an
instance declaration, must be unique. Ideally, there should only one sensible or legal way to implement the functions for that type. And, indeed, that’s how
Functor works, which is why we can easily derive
Functor instances. And since applicatives are functors, we might expect that to carry over, and most of the time it does work out that way. However, applicatives are not mere functors; they are monoidal functors.
Semigroup present some difficulties for the uniqueness expectation; there are almost always at least two valid
Semigroup instances for a given type, which Haskell accommodates via a profusion of newtypes. Due to the connection between monoids and applicative functors, applicatives can also sometimes have multiple valid implementations related to different monoids. They don’t always, and sometimes those implementations aren’t useful, but still. Lists are one case where there are two competing valid (and sometimes useful) instances.