One of the important concepts to understand about functional programming is functor. Unless one comes from a school of Haskell, looking at the functor‘s type signature for the first time is confusing at best. OK, maybe not for you, but for me:

fmap :: Functor f => (a -> b) -> f a -> f b

Sometime, the functor‘s type signature is also written as

class Functor f where
fmap :: (a -> b) -> f a -> f b

Sometime, the f a and f b above are written with no space between them, as following:

class Functor f where
fmap :: (a -> b) -> fa -> fb

OK, let’s make sense of all of the above.

First, what is a type signature? A type signature is a typeclass definition. That does not help at all. What is a typeclass? A typeclass in functional programming paradign is equivalent to an interface in OO paradigm. A typeclass consists of a list of functions. In the case of functor, its typeclass only lists one function fmap in its definition. Therefore, anything that imnplements the fmap function is a functor.

Second, what is f a and f b, or fa and fb? So f is a ‘context’, and f a (or fa, note: I will drop writing fa with no space between them from here on) represents the value a in this context. That’s fine if you’re not doing functional JavaScript programming. If you do, then the term ‘context’ can also becoming very confusing very quickly because in JavaScript the term ‘context’ also has another meaning. So when you see f a, think of it as a ‘box’ that contains the value a. You can also substitute ‘wrapper’ or ‘container’ for ‘box’. You can still call it a ‘context of a’ as long as you don’t mix up with the context in JavaScript.

Finally, here’s the meaning of the functor‘s type signature.

fmap says: give me a function that takes an a and returns a b, and a box that contains a, and I’ll return a box that contains b.

Alternatively, fmap says: give me a function that takes an a and returns a b, and an f of a, and I’ll return an f of b.

Now that we understand how to read type signature, let’s take a look at the type signature of another function, say add in Ramda. Its type signature is

add :: Number -> Number -> Number

If you’re reading with me right now, Ramda docs clearly says:

Number a 
The first value

Number b
The second value

Returns Number
The result of a+b

Adds 2 numbers (or strings). Equivalent to a + b but curried.

WT…? Actually, it makes sense. Once the function add is curried, it becomes a series of unary functions. Unary functions are functions that take only 1 input.

So add actually says: Give me a number, I’ll return a function that waits for a number, and when you supply another number, I’ll return a number (which is the sum of 2 supplied numbers)

So if now we want to write a function called add10 by supplying 10 as the first argument to add as follow

var add10 = add(10)

We can document our add10 function as

add10 :: Number -> Number

Hope that makes sense.