What is Functor ?

Michael
3 min readOct 8, 2023

--

(Previous series about Container)
(fp-ts series 2: Functor
)

  1. 👇🏻 What is Functor?

Functor in Programming

The term Functor could be confusing. Basically when we say Functor in programming sense, we refer to a “Container” that is “Mappable”. When you provide a “map” function that takes a function and transform it into a corresponding function in the “Container” world, it becomes “Mappable”.

When we have a “Container” that is “Mappable” and a “return” function that takes a data and transform it into the “Container” world, then you have a Functor! (Well, you still need to fulfil the Functor laws :) )

Map and Return function

Here is the type signature of “map” and “return” function in a functor.

/**
* The Map and Return function type signature in a functor
*/
type Map = (f: (a: A) => (b: B)) => (fa: Container<A>) => (fb: Container<B>)
type Return = (a: A) => (fa: Container<A>)

The “map” function takes a function that transforms the data into another type, then it takes a data wrapped with a “Container” and return the transformed data wrapped with the “Container”. The “map” function is also commonly known as “lift” if you look at the type signature this way:

/**
* map is also known as lift
*/
type Lift = (f: (a: A) => (b: B)) => ((fa: Container<A>) => (fb: Container<B>))

After it takes a function (f: (a: A) => (b: B)), it returns a “lifted” version function ((fa: Container<A>) => (fa: Container<B>)).

The implementation of “map” function should help you to unwrap the data from the “Container” (from fa to a ), perform the transformation using the function f (from a to b ), and then wrap the result b with the “Container” and return it (fb).

The “return” function is much simpler, it should just helps you to the wrap the data with the “Container” (from a to fa ).

Example — <Option> in fp-ts

Let’s take a look at the implementation of “map” and “return” function in <Option> in fp-ts.

/**
* Note: "return" is named as "of" in fp-ts (probably "return" is a reserved keyword in JS)
*/
/**
* Type in Option.d.ts
*/
export declare const map: <A, B>(f: (a: A) => B) => (fa: Option<A>) => Option<B>
export declare const of: Pointed1<URI>['of']

/**
* Implementation in Option.js
*/
var map = function (f) { return function (fa) {
return (0, exports.isNone)(fa) ? exports.none : (0, exports.some)(f(fa.value));
}; };
exports.of = exports.some;

(Quick review on Option)

In the implementation of “map” function in Option, it checks whether the Option value is None or Some(a). If it is None, it will just return None. Otherwise, it unwraps the value from Some(a) to a, apply the function f on the data a and return the result data b wrapped with Option (Some(b)).

For the “return” (of) function in Option, it will just help you to wrap the data with Option (from a to Some(a)).

Functor laws

There are two functor laws you need to follow if you are going to create your own functor: identity law and composition law.

/**
* identity law:
* map(id) = id

* composition law:
* map(compose(f, g)) = compose(map(f), map(g))
*/

id function is simply a function that returns data itself(a => a). The identity law tells us that after the “map” function takes the id function, it must the same as the id function in the “Container” (fa => fa).

The composition law tells us that when we compose two functions f and g, and then feed it into the “map” function, the resulting function should be the same as if you feed the function f and g into the “map” function first respectively and compose them afterwards.

What’s Next:

Next, we will discuss more on Applicative Functor, Monad, and the Monoid in depth.

More about fp-ts.

Thanks for reading 🫡
Hope you enjoy this article and gain something from it. I wish it is less daunting now for you to learn Functional Programming :)

Ka Hin

--

--

Michael

Software Engineer🧑🏻‍💻Master in Computer Science🎓. Helping people to learn and use Functional Programming in JS. F# and JS developer🧑🏻‍💻 FP-TS ➡️