【发布时间】:2012-08-17 14:10:18
【问题描述】:
当我发现自己在写以下几行然后敬畏地看着它们时,我正在玩 CoffeeScript:
compose = (f, g) -> (x) -> f g x
curry = (f) -> (x) -> (y) -> f(x, y)
uncurry = (f) -> (x, y) -> (f x) y
真好,我想!现在,作为一个练习,我想我会将 curry 和 uncurry 函数推广到 n args,以获得类似的东西:
curry2 = (f) -> (x) -> (y) -> f(x, y)
curry3 = (f) -> (x) -> (y) -> (z) -> f(x, y, z)
curry4 = (f) -> (x) -> (y) -> (z) -> (t) -> f(x, y, z, t)
对于 uncurry 也是一样:
uncurry2 = (f) -> (x, y) -> (f x) y
uncurry3 = (f) -> (x, y, z) -> ((f x) y) z
uncurry4 = (f) -> (x, y, z, t) -> (((f x) y) z) t
编写 n 元 uncurry 并不难:
uncurry = (n) -> (f) -> (args...) ->
if n == 1
f args[0]
else
((uncurry n - 1) f args.shift()) args...
另一方面,我不知道如何让 n 元咖喱起作用。我想先实现一个 curry_list 函数,它是这个套件的泛化:
curry_list2 = (f) -> (x) -> [x, y]
curry_list3 = (f) -> (x) -> (z) -> [x, y, z]
curry_list4 = (f) -> (x) -> (z) -> (t) -> [x, y, z, t]
下面是实现:
curry_list = (n) ->
curry_list_accum = (n, accum) ->
if n
(x) ->
accum.push x
curry_list_accum n - 1, accum
else
accum
curry_list_accum n, []
然后我只需将 curry_list 与函数应用程序组合起来即可获得柯里化。这就是我试图做的:
curry = (n) ->
apply_helper = (f) -> (args) -> f args...
(f) -> compose (apply_helper f), (curry_list n)
但由于某种原因,它不起作用。例如,尝试评估
curry(3)((a,b,c) -> a + b + c)(1)(2)(3)
产生以下错误:
Function.prototype.apply: 参数列表类型错误
现在在记了一些笔记之后,我明白尝试用 curry_list 组合 f 是不正确的。我确实有直觉,我正在寻找的是看起来像这个组合的东西,但不完全是那样。我这样想对吗?
最后,正确的实现是什么?
【问题讨论】:
-
我很敬畏你的问题。 +1,好先生。
-
我不久前写的这个 JS 实现可能会为你指明正确的方向:codingforums.com/showthread.php?t=138769
-
+1 严重混淆了我。有那么一刻我以为我在看haskell。
标签: javascript functional-programming coffeescript