A (FUNK)TOR!
But for real… Functors
“We abstract out a common pattern, make certain it follows some laws, give it an awesome name, and wonder how we ever lived without it”
I think this is an accurate reasoning for typeclasses. And was pre-highlighted in the book, so the person who sent it to me must of also thought so.
Functors is an example of the above, an abstraction of a common pattern. And that common pattern is mapping over a structure (or type).
The typeclass for functors is:
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
...
Which essentially says; given a type f
of Kind *->*
(A kind is essentially the type of a type), the method fmap
can be applied by passing a function of type a -> b
to a type of f
which takes an argument a
, to return a type of f b
.
Higher Kinded Types
In the above context, f
just means type, the most familiar for this application being the list type. In this context the f
is also referred to as the structure. And as mentioned above the for f
to be a functor, it must take a type as an argument, this is called a Higher Kinded Type. This is just a type level concept, analogous to a function taking a function as an argument to get a Higher Ordered Function.
The Rules
Functors, like all category theory typeclass abstractions, are law bound:
Identity: fmap id (f a) = f a
- This rule is kind of intuitive and is that if you map the id function over a higher kinded type, it will return the same higher kinded type.
Composition: fmap (g . f) = fmap g . fmap f
- This one allows for predictability and reliability when using Functors and it states that the mapped function over each individual type should equal the same as the function applied to the combined higher kinded type.
Both of these laws together work to preserve the structure of the container f
and allow you to lift your function over the container.
However you can create lawless Functors. These are the Functors that existed around 400 years ago, they use to gallop around the Great Plains of the Wild West, stealing cattle and not giving a damn about the Composition rule! But this is actually hard to do and kind of pointless because typeclasses are suppose to be predictable abstractions, so obey the Typeclass laws!
Here’s a post from MondayMorningHaskell on why you should obey these laws