Карринг - это преобразование одной функции из n аргументов в n функций с одним аргументом в каждой. Дана следующая функция:
function f(x,y,z) { z(x(y));}
Когда карри, становится:
function f(x) { lambda(y) { lambda(z) { z(x(y)); } } }
Чтобы получить полное применение f (x, y, z), вам нужно сделать это:
f(x)(y)(z);
Многие функциональные языки позволяют писать f x y z
. Если вы вызываете только f x y
или f (x) (y), тогда вы получаете частично примененную функцию - возвращаемое значение является закрытием lambda(z){z(x(y))}
с переданными значениями x и y to f(x,y)
.
Одним из способов использования частичного применения является определение функций как частичных приложений обобщенных функций, таких как fold :
function fold(combineFunction, accumulator, list) {/* ... */}
function sum = curry(fold)(lambda(accum,e){e+accum}))(0);
function length = curry(fold)(lambda(accum,_){1+accum})(empty-list);
function reverse = curry(fold)(lambda(accum,e){concat(e,accum)})(empty-list);
/* ... */
@list = [1, 2, 3, 4]
sum(list) //returns 10
@f = fold(lambda(accum,e){e+accum}) //f = lambda(accumulator,list) {/*...*/}
f(0,list) //returns 10
@g = f(0) //same as sum
g(list) //returns 10
Самый простой способ увидеть, чем они отличаются - рассмотреть реальный пример . Давайте предположим, что у нас есть функция,
Add
которая принимает 2 числа в качестве входных данных и возвращает число в качестве выходных, например,Add(7, 5)
возвращает12
. В этом случае:Частичное применение функции
Add
со значением7
даст нам новую функцию в качестве вывода. Эта функция сама принимает на вход 1 число и выводит число. В качестве таких:Итак, мы можем сделать это:
Каррирование функции
Add
даст нам новую функцию в качестве вывода. Эта функция сама принимает на вход 1 число и выводит еще одну новую функцию. Эта третья функция затем принимает 1 число в качестве ввода и возвращает число в качестве вывода. В качестве таких:Итак, мы можем сделать это:
Другими словами, «карри» и «частичное применение» - это две совершенно разные функции. Карринг требует ровно 1 ввода, тогда как частичное применение требует 2 (или более) входов.
Хотя они оба возвращают функцию в качестве вывода, возвращаемые функции имеют совершенно разные формы, как показано выше.
источник
n-ary
в(x - n)-ary
, каррируя изn-ary
вn * 1-ary
. Частично примененная функция имеет уменьшенную область применения (приложения), тоAdd7
есть менее выразительна, чемAdd
. С другой стороны, функция карри столь же выразительна, как и исходная функция.f2(7)(5) is just a syntactic shortcut
? (Я знаю очень мало.)f2
Уже не содержит / "знать о" 7?curry
где-нибудь реализация (не думаю, что она естьfunctools
)Примечание: это было взято из F # Basics отличной вводной статьи для разработчиков .NET, знакомящихся с функциональным программированием.
источник
Интересный вопрос После небольшого поиска «Приложение с частичными функциями не каррирует» дало лучшее объяснение, которое я нашел. Я не могу сказать, что практическая разница особенно очевидна для меня, но тогда я не эксперт по FP ...
Еще одна полезная страница (которую, признаюсь, я еще не полностью прочитал) - это «Каррирование и частичное приложение с Java-замыканиями» .
Имейте в виду, что эта пара терминов очень запутана.
источник
Я ответил на это в другой теме https://stackoverflow.com/a/12846865/1685865 . Короче говоря, частичное применение функции - это исправление некоторых аргументов данной функции с несколькими переменными, чтобы получить другую функцию с меньшим числом аргументов, в то время как Curry - это превращение функции из N аргументов в унарную функцию, которая возвращает унарную функцию ... [Пример Карри показано в конце этого поста.]
Карринг в основном представляет теоретический интерес: вычисления могут выражаться с использованием только унарных функций (т.е. каждая функция является унарной). На практике и как побочный продукт, это метод, который может сделать многие полезные (но не все) частичные функциональные приложения тривиальными, если в языке есть функции карри. Опять же, это не единственное средство для реализации частичных приложений. Таким образом, вы можете столкнуться со сценариями, в которых частичное применение выполняется другим способом, но люди принимают его за каррирование.
(Пример карри)
На практике не просто написать
или эквивалентный JavaScript
вместо
ради карри.
источник
Curry - это функция одного аргумента, которая принимает функцию
f
и возвращает новую функциюh
. Обратите внимание, чтоh
принимает аргументX
и возвращает функцию, которая отображаетсяY
наZ
:Частичное приложение - это функция двух (или более) аргументов, которая принимает функцию
f
и один или несколько дополнительных аргументовf
и возвращает новую функциюg
:Путаница возникает потому, что с функцией с двумя аргументами имеет место следующее равенство:
Обе стороны дадут одну и ту же функцию с одним аргументом.
Равенство неверно для функций с более высокой арностью, потому что в этом случае каррирование вернет функцию с одним аргументом, тогда как частичное применение вернет функцию с несколькими аргументами.
Разница также в поведении, в то время как карринг рекурсивно преобразует всю исходную функцию (по одному разу для каждого аргумента), частичное применение - это просто замена в один шаг.
Источник: Википедия Карри .
источник
Разницу между карри и частичным применением лучше всего проиллюстрировать на следующем примере JavaScript:
Частичное применение приводит к функции меньшей арности; в приведенном выше примере
f
имеет арность 3, аpartial
арность только 2. Что более важно, частично примененная функция будет возвращать результат сразу после вызова , а не другую функцию в цепочке каррирования. Так что, если вы видите что-то подобноеpartial(2)(3)
, это не частичное применение в действительности.Дальнейшее чтение:
источник
Простой ответ
Curry: позволяет вызывать функцию, разбивая ее на несколько вызовов, предоставляя один аргумент для каждого вызова.
Частичное: позволяет вызвать функцию, разделив ее на несколько вызовов, предоставив несколько аргументов для каждого вызова.
Простые подсказки
И то, и другое позволяет вам вызывать функцию, предоставляющую меньше аргументов (или, лучше сказать, кумулятивно). На самом деле оба они связывают (при каждом вызове) определенное значение с конкретными аргументами функции.
Реальная разница видна, когда функция имеет более 2 аргументов.
Простая е (с) (образец)
(в JavaScript)
Зачем всегда передавать аргументы, такие как контекст и обратные вызовы, если они всегда будут одинаковыми? Просто свяжите некоторые значения для функции
и вызвать его на subject1 и Foobar с
Удобно, не так ли? 😉
С карри вам нужно будет передавать один аргумент за раз
отказ
Я пропустил все академические / математические объяснения. Потому что я этого не знаю. Может быть, это помогло 🙃
источник
Во время обучения я много раз задавался этим вопросом, и с тех пор мне задавали его много раз. Самый простой способ, которым я могу описать разницу, состоит в том, что оба они одинаковы :) Позвольте мне объяснить ... есть очевидные различия.
Как частичное применение, так и каррирование включают предоставление аргументов функции, возможно, не все сразу. Довольно канонический пример - добавление двух чисел. В псевдокоде (фактически JS без ключевых слов) базовая функция может быть следующей:
Если бы я хотел добавить функцию addOne, я мог бы частично применить ее или карри:
Теперь их использование понятно:
Так в чем же разница? Что ж, это неуловимо, но частичное приложение включает в себя предоставление некоторых аргументов, и возвращаемая функция затем выполнит основную функцию при следующем вызове, тогда как каррирование будет ждать, пока у нее не будет всех необходимых аргументов:
Короче говоря, используйте частичное приложение для предварительного заполнения некоторых значений, зная, что при следующем вызове метода он будет выполняться, оставляя неопределенными все необеспеченные аргументы; используйте curry, если вы хотите постоянно возвращать частично примененную функцию столько раз, сколько необходимо для выполнения сигнатуры функции. Один последний надуманный пример:
Надеюсь это поможет!
ОБНОВЛЕНИЕ: Некоторые языки или реализации lib позволят вам передать arity (общее количество аргументов в окончательной оценке) частичной реализации приложения, которая может объединить два моих описания в запутанный беспорядок ... но в этот момент эти два метода в значительной степени взаимозаменяемы.
источник
Для меня частичное применение должно создать новую функцию, где используемые аргументы полностью интегрированы в результирующую функцию.
Большинство функциональных языков реализуют каррирование, возвращая замыкание: не оценивайте в лямбда-выражениях при частичном применении. Таким образом, для частичного применения, чтобы быть интересным, мы должны сделать различие между каррингом и частичным применением и рассматривать частичное применение как каррирование и оценку в лямбда-выражении.
источник
Я могу ошибаться, поскольку у меня нет достаточного опыта в теоретической математике или функциональном программировании, но из моего краткого опыта в FP, кажется, что карринг имеет тенденцию превращать функцию из N аргументов в N функций одного аргумента, тогда как частичное применение [на практике] лучше работает с переменными функциями с неопределенным числом аргументов. Я знаю, что некоторые примеры в предыдущих ответах не поддаются этому объяснению, но это помогло мне больше всего отделить понятия. Рассмотрим этот пример (написанный на CoffeeScript для краткости, приношу свои извинения, если он еще больше смущает, но, если необходимо, попросите разъяснений):
Это, очевидно, надуманный пример, но обратите внимание, что частичное применение функции, которая принимает любое количество аргументов, позволяет нам выполнять функцию, но с некоторыми предварительными данными. Каррирование функции аналогично, но позволяет нам выполнять функцию N-параметров по частям до, но только до тех пор, пока не будут учтены все N параметров.
Опять же, это мой взгляд из того, что я прочитал. Если кто-то не согласен, я был бы признателен за комментарий, а не за немедленное понижение. Кроме того, если CoffeeScript трудно читать, посетите coffeescript.org, нажмите «попробовать coffeescript» и вставьте в мой код, чтобы увидеть скомпилированную версию, которая может (надеюсь) иметь больше смысла. Спасибо!
источник
Я предполагаю, что большинство людей, которые задают этот вопрос, уже знакомы с основными понятиями, поэтому им нет необходимости говорить об этом. Это частичное совпадение.
Вы могли бы в полной мере использовать понятия, но вы понимаете их вместе как это псевдоатомное аморфное концептуальное размытие. Чего не хватает, так это знания, где находится граница между ними.
Вместо того, чтобы определять, что каждый из них, легче выделить только их различия - границы.
Карри - это когда вы определяете функцию.
Частичное применение - это когда вы вызываете функцию.
Приложение говорит по математике для вызова функции.
Частичное приложение требует вызова карри функции и получения функции в качестве возвращаемого типа.
источник
Здесь есть и другие замечательные ответы, но я считаю, что этот пример (согласно моему пониманию) в Java может быть полезным для некоторых людей:
Таким образом, каррирование дает вам функцию с одним аргументом для создания функций, где частичное приложение создает функцию-обертку, которая жестко кодирует один или несколько аргументов.
Если вы хотите копировать и вставлять, ниже будет шумнее, но удобнее работать, так как типы более мягкие:
источник
Написав это, я перепутал карри и не спеша. Это обратные преобразования функций. Это действительно не имеет значения, что вы называете, что, пока вы получаете то, что представляет преобразование и его обратное.
Непостоянство не очень четко определено (или, скорее, существуют «противоречивые» определения, которые все отражают дух идеи). По сути, это означает превращение функции, которая принимает несколько аргументов, в функцию, которая принимает один аргумент. Например,
Теперь, как вы превращаете это в функцию, которая принимает один аргумент? Вы обманываете, конечно!
Обратите внимание, что плюс теперь принимает один аргумент (который состоит из двух вещей). Супер!
какой в этом смысл? Что ж, если у вас есть функция, которая принимает два аргумента, и у вас есть пара аргументов, приятно знать, что вы можете применить функцию к аргументам и при этом получить то, что ожидаете. И на самом деле, сантехника для этого уже существует, так что вам не нужно делать такие вещи, как явное сопоставление с образцом. Все, что вам нужно сделать, это:
Так что же такое частичное применение функции? Это другой способ превратить функцию с двумя аргументами в функцию с одним аргументом. Это работает по-другому, хотя. Опять же, давайте возьмем (+) в качестве примера. Как мы можем превратить его в функцию, которая принимает один Int в качестве аргумента? Мы обманываем!
Это функция, которая добавляет ноль к любому Int.
добавляет 1 к любому Int. И т. Д. В каждом из этих случаев (+) «частично применяется».
источник