How to use a pointed functor

I am trying to get to know functional programming in JavaScript. I just read that a functor pointer:

An object with the of function that places any one value in it.

ES2015 adds Array.of , making arrays a pointed functor.

And my question is what exactly means “one meaning”?

I want to create a Functor / Container (e.g. https://drboolean.gitbooks.io/mostly-adequate-guide/content/ch8.html ) that contains a grid of a given size (width, height) as a 1-dimensional array and allows me do the conversion on it. As a simple object, I would save 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 it right.

I know that in order to store a single value, it is quite fine to use the specified functor:

 Container.of(47) 

But is it normal to use an object as a value, assuming that the 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]) 
+5
source share
2 answers

The explanation at https://github.com/hemanth/functional-programming-jargon , unfortunately, is not very accurate.

A The indicated functor is indeed a functor F together with the of function defined for each type a and sends the value x type a to the value of(x) type F a . The signature of Hindley-Milner is as follows:

 of :: a -> F a 

For example, the Array function is specified using of = x => [x] defined for each value x any type a .

In addition, the function of (or, more precisely, the set of functions of , as you have for each type of a ), must be a natural transformation from an identity functor to F This means that of value of the function is equal to of argument displayed by the same function:

 of(f(x)) === of(x).map(f) 

For example, in the Array example, you have

 [f(x)] === [x].map(f), 

therefore x => [x] indeed a natural transformation.

But you can also take

 of = x => [x, x] [f(x), f(x)] === [x, x].map(f) 

which is another pointed functor, even if the map functor remains unchanged. (Note that in each case you only get special arrays as the values of(x) .)

However, you cannot take, for example.

 of = x => [x, 0] [f(x), 0] !== [x, 0].map(f) 

Now

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

works fine and returns your object passed to the Grid . You can then map your Grid to any regular F function from simple objects to simple objects, and the result will be the same as applying F and transferring to the Grid due to the law of natural transformation. Note that this way you can also call Grid.of with any other value, for example Grid.of({width: 2}) even Grid.of(2) . Alternatively, you can restrict the types for which Grid.of is defined, then the value should be only the type that you allow.


This is a little tricky:

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

This applies to Grid.of for several arguments. Since Grid.of by definition a function of only one argument, the result will be Grid.of(2) , which may not be what you want. If you really want to supply all the values, you probably want to write

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

Alternatively, you can extend Grid.of by several arguments, first wrapping them in an array inside, and then applying Grid.of It really depends on what you are after.

For an example of real-world use, see, for example, here , where a "boring" task is defined through Task.of from a simple value. On the other hand, here is a more interesting task wrapping a function that you would not get with Task.of The important thing is that both Tasks can be used with the same uniform interface, as shown in both examples.

Also note that applicative functors are not used in these examples, so pointed functors are still used without use.

+5
source

But is it normal to use an object as a value, assuming that the object is a "single value":

Yes. of should take any value and put it in a container. The object, of course, is such a single meaning.

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

No. of should take one parameter. If you want to put several values ​​inside a functor, put them inside another structure and place this structure inside a functor or create a functor with something other than its point function ( of ).

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

No, if you expect to return the input, this will not work. of should take input as-is and wrap the structure around it. In the case of your grid, this will 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]); } } 

Thus, the aforementioned call would create a Grid objects, rather than a grid of four numbers. Note that of not the only way to build an instance of a functor, it is only a way to create an instance from a single element.

Note that of is most important as part of the applicative, not so interesting for ordinary functors. By the way, if you are interested in the concepts of functional programming, you can also make your Grid monoid, traverse and monad - see https://github.com/fantasyland/fantasy-land .

+4
source

All Articles