jesper jesper - 3 months ago 15
Javascript Question

How to use pointed functor properly

I'm trying to get familiar with functional programming in JavaScript. I've just read that pointer functor is:


An object with an
of
function that puts any single value into it.

ES2015 adds
Array.of
making arrays a pointed functor.


And my question is what does exactly mean "single value"?

I want to make a Functor/Container (like in https://drboolean.gitbooks.io/mostly-adequate-guide/content/ch8.html) that holds grid of given dimension (width, height) as 1-dimensional array and allows me to do transformations on it. As a plain object I would store it as
{ width: 2, height: 2, list: [1, 2, 3, 4] }
but I want to put it in a functor and I'm not sure how to do properly.

I know that it's perfectly fine to use pointed functor like this to store single value:

Container.of(47)


But is it ok to use object as value assuming object is a "single value":

Grid.of({ width: 2, height: 2, list: [1, 2, 3, 4] })


Or even like this:

Grid.of(2, 2, [1, 2, 3, 4])

Answer

But is it ok to use object as value assuming object is a "single value":

Yes. of is supposed to take any value and put it inside the container. An object certainly is such a single value.

Grid.of(2, 2, [1, 2, 3, 4])

No. of is supposed to take a single parameter. If you want to put multiple values inside a functor, put them inside an other structure before and put that structure inside the functor, or construct the functor by something else than its point function (of).

Grid.of({ width: 2, height: 2, list: [1, 2, 3, 4] })

No, if you expect that to return the input then it won't work. of should take the input as-is and wrap the structure around it. In case of your grid, it would most certainly look like this:

// Grid<A>
class Grid {
    // Int -> Int -> [A] -> Grid<A>
    constructor(w, h, vals) {
        assert(Number.isInteger(w) && Number.isInteger(h));
        this.width = w;
        this.height = h;
        const list = Array.from(vals);
        assert(list.length == w * h);
        this.list = list;
    }
    // Grid<A> -> (A -> B) -> Grid<B>
    map(f) {
        return new Grid(this.width, this.height, this.list.map(f));
    }
    // A -> Grid<A>
    static of(x) {
        return new Grid(1, 1, [x]);
    }
}

So the above call would create a Grid of objects, not a grid of four numbers. Notice that of is not the only way to construct an instance of a functor, it's only the way to construct an instance from a single element.

Notice that of is most important as part of an Applicative, not so much interesting for ordinary Functors. Btw, if you're interested in functional programming concepts, you should also be able to make your Grid a Monoid, a Traversable and a Monad - see https://github.com/fantasyland/fantasy-land.