Я играл с 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-ary uncurry было не очень трудным:
uncurry = (n) -> (f) -> (args...) ->
if n == 1
f args[0]
else
((uncurry n - 1) f args.shift()) args...
С другой стороны, я не могу понять, как заставить n-ary карри работать.Сначала я подумал о реализации функции 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: список аргументов имеет неправильный тип
сейчаспосле нескольких заметок я понимаю, что попытка составить f с помощью curry_list некорректна.У меня есть интуиция, что я ищу что-то похожее на эту композицию, но это не совсем так.Правильно ли я считаю, что?
Наконец, что будет правильной реализацией?