In Professor Frisby Introduces Composable Functional JavaScript the identity functor was introduced:
const Box = x =>
({
map: f => Box(f(x)),
fold: f => f(x) // for testing
})
I spent the better part of the day understanding functors and why the above JavaScript code is actually the identity functor. So I thought I would alter it to get a "real" functor that is not the identity functor. I came up with this:
const Endo = x =>
({
map: f => Endo(f(x).split('')),
fold: f => f(x).split('') // for testing
})
My reasoning is that with Box, Id_Box: Box -> Box
and Id_Box f = f
. Endo would also map to itself but Endo(f): Endo(x) -> Endo(y)
(if f: x -> y
).
Am I on the right track?
EDIT:
Replaced string
with the more generic x
as it was in the original examples.
As pointed out in this answer, for our purposes as programmers we can treat all functors as endofunctors so don't get too caught up on the differences.
As for what a functor is, in brief it is
Array.prototype.map
)xs === xs.map(x => x)
xs.map(f).map(g) === xs.map(f . g)
where.
is function composition.That's it. No more, no less. Looking at your
Box
, it's a data structure that has amap
function (check 1 & 2) and that map function looks like it should respect identity and composition (check 3 & 4). So it's a functor. But it doesn't do anything, which is why it's the identity functor. Thefold
function isn't strictly necessary, it just provides a way to 'unwrap' the box.For a useful functor, let's look at JavaScript arrays. Arrays actually do something: namely they contain multiple values rather than just a single one. If an array could only have one element, it'd be your
Box
. For our purposes we'll pretend that they can only hold values of the same type to simply things. So an array is a data structure, that has a map function, that respects identity and composition.So when we
map
a function over a functor (array) we get back another instance of the same functor (a new Array) with the function applied to whatever the functor (array) was holding.So now lets look at another ubiquitous JavaScript data structure, the object. There's no built in
map
function for objects. Can we make them a functor? Assume again that the object is homogenous (only has keys to one type of value, in this example Number):And you can continue on to test that the function accurately (as far as is possible in JavaScript) supports identity and composition to satisfy the functor laws.