April 26, 2018

Functors, Monoids, and other scary things

Haskell introduces a number of scary sounding concepts and entities. The first thing is not to be intimidated by all this new language. In general, it turns out that these are fairly straightforward, albeit abstract concepts.

Anyone who has some experience in mathematics, will be used to confronting new words for abstract concepts. Anyone who has studied abstract algebra will have confronted groups, rings, and fields. The first thing is to discard any preconceived notion of what a "ring" is and start from scratch. Haskell takes a different approach. Rather than taking common words like "ring" or "group", they find some word like "functor" without much baggage attached and use it to label a concept.

By and large these Haskell concepts are abstract data types. In other words we have a set of entities along with one or more operators, and some rules that define how they behave. The whole mess is the abstract data type.

Monoids

The important thing to know about Monoids is that they are as simple as dirt, especially if you have had any kind of class in abstract algebra. Despite their name, understanding Monoids is not a tremendous help or stepping stone towards understanding Monads. A Monoid is a system with the following properties: And that is it. The integers along with the addition operator (+) and zero as the identity form a monoid. Similarly, the integers with multiplication and one as the identity form a monoid. As you can see, Monoids are commonplace and ubiquitous. They are also useless, at least they have been for me in my use of Haskell thus far.

Functors

One approach to explaining Monads is to progress from Functors to Applicative Functors to Monads. For now we will be satisfied to just understand a Functor.

Start by understanding the "map" function. Given a function and a list of items, "map" applies the function to each item in the list and provides us with a list of modified items. A functor is simply a generalization of this concept. In the generalization, map becomes fmap, and the list becomes the functor. So a functor is any kind of container like item that fmap can be applied to. Note in particular that the functor is the target of fmap, not the function being applied to the items in the functor.

Note also that "map" is needless once you have fmap, since a list is a sort of functor and fmap will do just fine. There has been a fair bit of discussion about whether or not to keep map around and/or rename fmap to map if it was eliminated. The thinking seems to be that for Haskell beginners, learning map and lists in a simpler world is a good thing. So if you find yourself asking why Haskell has both fmap and map, you probably have a grip on Functors as you should.

Applicative Functors


Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org