jes*_*per 5 javascript functional-programming functor
我正在尝试熟悉JavaScript中的函数式编程.我刚看到指针仿函数是:
具有
of将任何单个值放入其中的函数的对象.ES2015增加了
Array.of使数组成为一个尖锐的算符.
而我的问题是"单一价值"究竟意味着什么?
我想制作一个Functor/Container(如https://drboolean.gitbooks.io/mostly-adequate-guide/content/ch8.html),它将给定尺寸(宽度,高度)的网格保持为一维数组,允许我对它进行转换.作为一个普通的对象,我会把它存储为{ width: 2, height: 2, list: [1, 2, 3, 4] }但我想把它放在一个仿函数中,我不知道如何正确地做.
我知道使用像这样的尖头仿函数存储单个值是完全没问题的:
Container.of(47)
Run Code Online (Sandbox Code Playgroud)
但是,如果对象是"单值",那么将对象用作值是否可以:
Grid.of({ width: 2, height: 2, list: [1, 2, 3, 4] })
Run Code Online (Sandbox Code Playgroud)
或者甚至像这样:
Grid.of(2, 2, [1, 2, 3, 4])
Run Code Online (Sandbox Code Playgroud)
遗憾的是,https://github.com/hemanth/functional-programming-jargon中的解释并不十分准确.
甲尖算符确实是一个算符F与函数一起of用于定义每一个类型 a中,发送值x类型的a成值of(x)类型的F a.在Hindley-Milner签名中,它看起来像这样:
of :: a -> F a
Run Code Online (Sandbox Code Playgroud)
例如,指向Array仿函数of = x => [x],为x任何类型的每个值定义a.
此外,函数of(或者更确切地说,函数的集合,of因为每种类型都有一个函数a)必须是从身份函子到...的自然转换F.这意味着of应用于函数的值等于of应用于函数的参数,然后映射到函数上:
of(f(x)) === of(x).map(f)
Run Code Online (Sandbox Code Playgroud)
例如,在您拥有的Array示例中
[f(x)] === [x].map(f),
Run Code Online (Sandbox Code Playgroud)
所以x => [x]确实是一种自然的转变.
但你也可以重新定义of为
of = x => [x, x]
[f(x), f(x)] === [x, x].map(f)
Run Code Online (Sandbox Code Playgroud)
这使得Array进入另一个尖锐的仿函数,即使map方法保持不变.(请注意,在每种情况下,您只能获得非常特殊的数组作为值of(x).)
但是,您无法定义您of的例如
of = x => [x, 0]
[f(x), 0] !== [x, 0].map(f)
Run Code Online (Sandbox Code Playgroud)
现在
var grid = Grid.of({ width: 2, height: 2, list: [1, 2, 3, 4] })
Run Code Online (Sandbox Code Playgroud)
完全没问题,并返回传递包裹的对象Grid.然后,您可以grid使用f普通对象将任何常规函数映射到普通对象,并且由于自然转换定律,结果将与应用f和包装相同Grid.请注意,通过这种方式,您还可以Grid.of使用任何其他值来调用Grid.of({width: 2})even Grid.of(2).或者,您可以限制Grid.of已定义的类型,然后该值必须只是您允许的类型.
这个有点棘手:
Grid.of(2, 2, [1, 2, 3, 4])
Run Code Online (Sandbox Code Playgroud)
这适用Grid.of于几个论点.因为Grid.of根据定义,只有一个参数的函数,结果将是Grid.of(2),这可能不是你想要的.如果你真的想要提供所有值,你可能想写
Grid.of([2, 2, [1, 2, 3, 4]])
Run Code Online (Sandbox Code Playgroud)
或者,您可以Grid.of通过在内部将它们预先包装到数组中然后应用来扩展到多个参数Grid.of.这真的取决于你追求的是什么.
对于现实世界的用法示例,请参见此处,其中"无聊"任务是通过Task.of普通值定义的.另一方面,这是一个更有趣的任务包装你不会得到的功能Task.of.但重要的是,两个任务都可以使用与两个示例中所示相同的统一接口.
另请注意,在这些示例中没有使用应用程序仿函数,因此仍然使用尖头仿函数而不是应用程序.
添加.
另请参阅https://github.com/MostlyAdequate/mostly-adequate-guide-it/blob/master/ch9.md#pointy-functor-factory以获得Pointed Functor的精彩介绍和实际使用.