Имея функцию f, которая принимает аргументы x 1 , x 2 ,…, x n
- т.е. f: X 1 × X 2 ×… × X n → Y
- curry переопределяет f как функцию, принимающую один аргумент a 1, который отображается на еще одну функцию. Этот метод полезен для частичного применения, например, с помощью pow
функции карри, которую мы могли бы написать exp = pow(e)
.
пример
Предполагая, что у нас есть следующая функция f, принимающая три аргумента ( f: X 1 × X 2 × X 3 → Y ):
def f(a,b,c):
return a + b * c
Карринг этой функции оставляет нас с f_curry: X 1 → (X 2 → (X 3 → Y)) , если бы мы теперь вызывали эту функцию дважды, f_curry(1)(2)
мы бы получили функцию ( h
), эквивалентную следующему:
def h(c):
return 1 + 2 * c
Функция карри f
может быть написана так (Python 3):
def f_curry(a):
def g_curry(b):
def h(c):
return a + b * c
return h
return g_curry
Вызов
Ваша задача будет заключаться в том, чтобы карри функции, как описано выше, вот правила:
- Ввод будет функцией черного ящика, которая принимает как минимум 2 аргумента
- Функция ввода всегда будет иметь фиксированное количество аргументов (в отличие
printf
или аналогично, обратите внимание: вам нужно поддерживать функции с любым количеством аргументов ≥2) - Если в вашем языке по умолчанию используются функции карри (например, Haskell), вы можете ожидать, что функция ввода будет определена для N- кортежей, а не для «функции более высокого порядка».
- Вы можете принять количество аргументов в качестве ввода
- Выход будет эквивалентным карри ввода *
- Вы можете предположить, что функция вывода будет только когда-либо:
- вызывается с меньшим или равным количеству аргументов, которые принимает входная функция
- вызывается с аргументами правильного типа
* Это будет означать для входных данных f
с N
аргументами и выходных данных, h
что для всех допустимых аргументов, a1,…,aN
он содержит это f(a1,a2,…,aN) == h(a1)(a2)…(aN)
.
def f(a,b,c): return a + b * c
а выход естьdef f_curry(a): def g_curry(b): def h(c): return a + b * c return h return g_curry
?f
(который где-то определен), а результат должен быть чем-то эквивалентнымf_curry
. Или вход будет,lambda a,b,c: a+b*c
а выход - функцией, эквивалентнойf_curry
.Ответы:
JavaScript (ES6), 35 байт
источник
Идрис , 204 байта
Попробуйте онлайн!
Звучит как работа для зависимых типов! Что же, может быть.
C - это функция типа карри. Для данного вектора типов a = [t 1 , t 2 ,… t n ] и функции типа T: HVect a → Type он возвращает новый тип:
Здесь HVect - гетерогенный векторный тип из Idris Prelude - тип n- кортежей, элементы которых имеют n разных типов.
с представляет собой функцию , которая принимает и Т , как неявных аргументов, а затем преобразует uncurried функцию типа ((б: HVect а) → T B) в каррированной одного типа C A T .
f
( C просто описывает то, что мы хотим сделать; c на самом деле делает это. Но мы не можем обойтись без определения C , поскольку Idris требует, чтобы каждое определение верхнего уровня имело сигнатуру типа.)
Ссылка TIO дает пример использования. Если мы определим функцию для трех кортежей (Nat, Nat, String) следующим образом:
затем
uncurried [3, 4, "th"]
дает тот же результат, что иc uncurried 3 4 "th"
. Идрис выводит аргументыa=[Nat, Nat, String]
иT=const String
для нас, я считаю.Я основал этот код на этой сути Timjb.
источник
HVect
по умолчаниюHVect
- это, по сути, кортеж, который вы можете отключить.Python 3 ,
5453 байтаПопробуйте онлайн!
источник
R , 96 байт
Попробуйте онлайн!
Предыдущая версия (97 байт)
-1 байт благодаря @JayCE
источник
Кокос , 54 байта
Попробуйте онлайн!
Кокос , 40 байт
Порт Эрика Python ответ .
Попробуйте онлайн!
источник
Python 2 , 60 байт
Попробуйте онлайн!
Нижний колонтитул - это тестер, который использует STDIN для каждой строки следующим образом:
[a,b,...]
)Обратите внимание, что, хотя список аргументов задается в качестве входных данных в тестере, в действительности, карри-эквивалент добавляется к списку, а список сокращается при вызове функции.
Аналогичная 55-байтовая версия была любезно предоставлена ovs :
Попробуйте онлайн!
источник
Цветная капуста , 84 байта
Попробуйте онлайн!
источник
Perl 6 ,
4240 байтПопробуйте онлайн!
-2 байта благодаря Брэду Гилберту b2gills .
источник
*
, это необходимо, только если после этого есть что-то подобное.assuming(*,1)
.Python 2 , 78 байт
Попробуйте онлайн!
источник
Атташе , 5 байт
Попробуйте онлайн!
Простой встроенный, во многом неинтересный. Но вот версия с нуля:
Атташе, 35 байт
Объяснение:
источник
Java 8, 46 + 318 = 364 байта
Это лямбда карри (хах), которая берет функцию и количество аргументов и возвращает функцию карри.
Попробуйте онлайн
Тип представления
Функция ввода
Функция input - это объект с единственным методом (исключая унаследованные методы), представляющим функцию. Обратите внимание, что стандартный функциональный интерфейс не может использоваться в качестве типа ввода, поскольку должны поддерживаться функции (например, 3 параметра). Также обратите внимание, что
java.util.function.Function
может быть передано лямбда-выражение, приведенное к стандартному типу (единственный метод -apply
).Проверенные исключения могут быть объявлены во входной функции, но они не могут быть выброшены (то есть они не будут переданы вызывающей стороне выходной функции). Предполагается, что это приемлемо, потому что функциональные интерфейсы Java не разрешают проверенные исключения (и их распространение не позволит отправке возвращать a
Function
). Исключения времени выполнения (присваиваемыеRuntimeException
илиError
) распространяются.Функция выхода
Результатом представления является
java.util.function.Function<Object, Object>
. Я подумал о возврате равниныObject
сapply
методом (как во входных данных), но тогда потребовалось бы отражение, чтобы вызвать результат, который казался достаточно неудобным, чтобы его можно было запретить - в частности, вызов всего пути вниз был бы невозможен за один раз. выражение.использование
Поскольку отправка возвращает функцию из
Object
вObject
, выходные данные могут быть вызваны напрямую (с помощьюapply
), но последующие промежуточные возвращаемые значения должны быть преобразованы в соответствующий тип (напримерjava.util.function.Function<Object, Object>
) перед вызовом. Консультируйтесь с TIO для некоторых примеров использования.Обратите внимание, что в Java функции (то есть методы) не являются объектами первого класса. Таким образом, синтаксис, используемый в выходном маркере описания вызова, не имеет смысла в Java. Скорее, чем
f(a1, a2, a3)
мыf.apply(a1, a2, a3)
, и, скорее, чемf(a1)(a2)(a3)
мы имеемf.apply(a1).apply(a2).apply(a3)
.Ограничения
Когда применяется промежуточный результат (добавлен аргумент), результат фактически является видоизмененной копией исходного результата. Например, в этом фрагменте:
строка 4 будет напечатана
4
, но строка 5 потерпит неудачу, потому что к тому времениc2
уже содержит аргументы2
и2
(обратите внимание, чтоc2 == c
). Это нарушает дух карри, но отвечает конкретным требованиям, указанным в вызове.Ungolfed
См. TIO для разглаженной копии.
источник
Юлия 0,6 , 48 байтов
Попробуйте онлайн!
Порт @ EricTheOutgolfer's Python ответа.
источник
APL (Дьялог Классик) ,
5857 байтПопробуйте онлайн!
Синтаксис вызова (с функцией карри
g
, аргументыx1
черезx3
и количеством аргументовn
):((n x1 f g) x2) x3
требует
⎕IO←1
источник