Является ли раздел результатом каррирования?

В программировании в Хаскеле Хаттоном

В общем, если # является оператором, то выражения вида (#), (x #), а также (# y) для аргументов x а также y называются разделами, значение которых как функции можно формализовать с помощью лямбда-выражений следующим образом:

(#)   =   \x  ->  (\y ->  x   #   y)
(x    #)  =   \y  ->  x   #   y
(#    y)  =   \x  ->  x   #   y

В чем разница между "разделом" и "карри"?

Является ли раздел результатом применения операции каррирования к функции с несколькими аргументами?

Благодарю.

3 ответа

Решение

Левые и правые секции являются синтаксическими устройствами для частичного применения инфиксного оператора к одному аргументу (см. Также ответ Чепнера). Для точности отметим, что карри - это не то же самое, что частичное применение:

  • Карринг - это преобразование функции, которая принимает N аргументов, в функцию, которая принимает один аргумент и возвращает функцию, которая принимает N-1 аргументы.

  • Частичное приложение создает функцию, которая принимает N-1 аргументов из функции, которая принимает N аргументов, предоставляя один из аргументов.

В Хаскеле бывает, что все карри; все функции принимают только один аргумент (даже неиспользуемые функции в Haskell принимают кортеж, который, строго говоря, является единственным аргументом - вы можете поиграть с curry а также uncurry функции, чтобы увидеть, как это работает). Тем не менее, мы очень часто неофициально думаем о функциях, которые возвращают функции как функции нескольких аргументов. С этой точки зрения, приятным следствием каррирования по умолчанию является то, что частичное применение функции к первому аргументу становится тривиальным: в то время как, например, elem принимает значение и контейнер и проверяет, является ли значение элементом контактера, elem "apple" берет контейнер (из строк) и проверяет, "apple" является элементом этого.

Что касается операторов, когда мы пишем, например...

5 / 2

... мы подаем заявку на оператора / к аргументам 5 а также 2, Оператор также может использоваться в префиксной форме, а не в инфиксной:

(/) 5 2

В префиксной форме оператор может быть частично применен обычным способом:

(/) 5

Это, однако, возможно, выглядит немного неловко - в конце концов, 5 здесь числитель, а не знаменатель. Я бы сказал, что в этом случае синтаксис левого раздела проще для глаз:

(5 /)

Кроме того, частичное применение ко второму аргументу не так просто написать, требуя лямбда или flip, В случае операторов, правильный раздел может помочь с этим:

(/ 2)

Обратите внимание, что разделы также работают с функциями, превращенными в операторы через синтаксис backtick, так что...

(`elem` ["apple", "grape", "orange"])

... берет строку и проверяет, можно ли ее найти в ["apple", "grape", "orange"],

Раздел - это просто специальный синтаксис для применения инфиксного оператора к одному аргументу. (# y) является более полезным из двух, так как (x #) эквивалентно (#) x (который просто применяет инфиксный оператор как функцию к одному аргументу обычным способом).

curry f x y = f (x,y), uncurry g (x,y) = g x y,

(+ 3) 4 = (+) 4 3 = 4 + 3, (4 +) 3 = (+) 4 3 = 4 + 3,

Раздел является результатом частичного применения карри функции: (+ 3) = flip (+) 3, (4 +) = (+) 4,

Функция карри (как g или же (+)) ожидает своих аргументов по одному. Некурри функция (как f) ожидает своих аргументов в кортеже.

Чтобы частично применить некритированную функцию, мы должны сначала превратить ее в каррированную функцию с curry, Чтобы частично применить карри функцию, нам ничего не нужно делать, просто примените ее к аргументу.

curry   :: ((a, b)  -> c ) -> ( a -> (b -> c))
uncurry :: (a -> (b -> c)) -> ((a, b)   -> c )

 x :: a
 g :: a -> (b -> c)       
--------------------
 g    x ::  b -> c  

 x       ::  a
 f       :: (a, b)   -> c
---------------------------
 curry f ::  a -> (b -> c)
 curry f     x ::  b -> c
Другие вопросы по тегам