One of the things that people new to Haskell may not appreciate is that academia’s love affair with monads has been waning for some time. In its place is a more nuanced hierarchy of Functor, Applicative, Monad. (*)
So what the heck is a functor? Well, really it’s just something you can map over and it makes sense. “Makes sense” has a specific mathematical meaning, but I’m going to gloss over it and keep going.
Let’s talk about some things you can map over:
- A list,
[a]
- A set,
Set a
- A nullable value,
Maybe a
- A random value,
Rand StdGen a
- A function returning a value,
(->) a
- A program returning a value,
IO a
(We’ll ignore this one from now on, I’m just mentioning it because IO is kind of important.) - A record, where we only map over one of the fields. e.g. imagine a pair
(x,y)
where x and y are different types
So, if you were mapping “add one” you’d get
- A list where all of the values were one larger e.g. [2,4] becomes [3,5]
- A set where all of the values were one larger e.g. #(2,4) becomes #(3,5).
- A value one larger, or null. So null becomes null, and 3 becomes 4.
- A random integer value between 1 and 6 becomes a random integer value between 2 and 7.
- A function f(x) becomes a function g(x) where g(x) = f(x) + 1
- The pair (x,y) becomes (f(x),y)
I’ve found that while getting your head around the concept, it’s best to just concentrate on nullable values and lists. In particular, if you’re familiar with Clojure or LINQ, it’s about understanding that things like nil-punning and fnil
are exactly the same concept as map and behave the same way.
Just to complicate matters, the set example doesn’t actually work in Haskell, but I’ll get to that in a later post.
My Head is Hurting
If you want to learn the stuff I’m saying properly, go do Brent Yorgey’s Introductory Haskell course and do the exercises. It’s a significant time investment, but well worth it.
(*) This is a gross over-simplification, so sue me.