A functor helps control complexity by placing a value in a container and applying transformations without exposing the value directly. This approach reduces scattered null checks and error-handling responsibilities. section 5.0
A functor is a data structure that supports fmap: open the container, apply a function to its value, and return the result in a new container of the same type. Each mapping can preserve immutability because it creates a new wrapper. section 5.2
Mapping over a Wrapper
const plus = R.curry((a, b) => a + b);\nconst plus3 = plus(3);\nconst two = wrap(2);\n\nconst five = two.fmap(plus3); // Wrapper(5)\nfive.map(R.identity); // 5\n\ntwo.fmap(plus3).fmap(plus10); // Wrapper(15) section 5.2
A basic functor workflow is:
- Wrap a value in a container. section 5.2
- Use fmap to apply a function inside the container. section 5.2
- Receive a new container and chain another fmap when more transformations are needed. section 5.2
Listing 5.1. Functional data type to wrap values
class Wrapper {
constructor(value) { #A
this._value = value;
}
// map :: (A -> B) -> A -> B
map(f) {
return f(this._value);
}
// fmap :: (A -> B) -> Wrapper[A] -> Wrapper[B]
fmap (f) { #B
return new Wrapper(f(this._value));
}
toString() {
return 'Wrapper (' + this._value + ')';
}
};
// wrap :: A -> Wrapper(A)
const wrap = (val) => new Wrapper(val); #C
module.exports = {
wrap: wrap,
Wrapper: Wrapper
};
The Wrapper implementation makes the distinction between ordinary map, which exposes the transformed value, and fmap, which returns a new Wrapper. section 5.2





