admin管理员组文章数量:1296489
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 .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])
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])
Share
edited Aug 27, 2016 at 11:16
jesper
asked Aug 27, 2016 at 10:02
jesperjesper
8898 silver badges21 bronze badges
8
-
what is
Foo.of
? did you mean Array.of? I thought, as of Es2015, only Array and TypedArray hadof
– Jaromanda X Commented Aug 27, 2016 at 10:11 - And what is your expected output? Didn't quite get your point. – Leo Commented Aug 27, 2016 at 10:15
-
Please give an example of your input data, and expected resulting array content - as it stands, you've confused me with
Foo
– Jaromanda X Commented Aug 27, 2016 at 10:17 -
1
In ES5
Array.of
is pointed function because, unlikeArray
, it interprets passed arguments in a single way no metter what arguments and how many arguments you pass, whileArray
differently interpretsArray(5)
andArray(5, 7)
. If you want to make yourFoo.of
a pointed function, force it to interpret arguments in a single way no matter what you pass to it. – user6586783 Commented Aug 27, 2016 at 10:23 - Maybe you are looking for an approach to flatten multi-dimensional array? – Leo Commented Aug 27, 2016 at 10:28
2 Answers
Reset to default 9The explanation in https://github./hemanth/functional-programming-jargon is unfortunately not very accurate.
A pointed functor is really a functor F
together with a function of
defined for every type a
, and sending a value x
of type a
into a value of(x)
of type F a
. In Hindley-Milner signature it looks like this:
of :: a -> F a
For instance, the Array functor is pointed with of = x => [x]
, defined for every value x
of any type a
.
Further, the function of
(or more precisely, the collection of functions of
as you have one for each type a
) must be a natural transformation from the identity functor into F
. Which means that of
applied to a function's value equals of
applied to the function's argument and then mapped over the function:
of(f(x)) === of(x).map(f)
For instance, in the Array example you have
[f(x)] === [x].map(f),
so x => [x]
is indeed a natural transformation.
But you can also redefine of
as
of = x => [x, x]
[f(x), f(x)] === [x, x].map(f)
which makes Array
into another pointed functor, even if the map
method remains the same. (Note that in each case, you only get very special arrays as values of of(x)
.)
However, you cannot define your of
as e.g.
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] })
is perfectly ok and returns your object passed wrapped into Grid
. Then you can map your grid
with any regular function f
from plain objects into plain objects and the result will be the same as applying f
and wrapping into Grid
, because of the natural transformation law. Note that this way you can also call Grid.of
with any other value like Grid.of({width: 2})
of even Grid.of(2)
. Alternatively, you can restrict the types for which Grid.of
is defined, then the value must only be of a type that you allow.
This one is a bit tricky:
Grid.of(2, 2, [1, 2, 3, 4])
This applies Grid.of
to several arguments. Since Grid.of
is 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 feed all values, you probably want to write
Grid.of([2, 2, [1, 2, 3, 4]])
Alternatively, you can extend Grid.of
to multiple arguments by pre-wrapping them into an array internally and then applying Grid.of
. It really depends on what you are after.
For a real world usage example, see e.g. here where a "boring" Task is defined via Task.of
from a plain value. On the other hand here is a more interesting Task wrapping a function that you wouldn't get with Task.of
. What is important though, is that both Tasks can be used with the same uniform interface as shown on both examples.
Also note that no applicative functors are used in these examples, so there are still uses of pointed functors without being applicative.
ADDED.
See also https://github./MostlyAdequate/mostly-adequate-guide-it/blob/master/ch9.md#pointy-functor-factory for a nice introduction and real world uses of the Pointed Functor.
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./fantasyland/fantasy-land.
本文标签: javascriptHow to use pointed functor properlyStack Overflow
版权声明:本文标题:javascript - How to use pointed functor properly - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741623078a2388924.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论