Частичное применение с инфиксными функциями

В то время как я немного понимаю о карри в математическом смысле, частичное применение инфиксной функции было новой концепцией, которую я открыл после того, как окунулся в книгу " Изучите вас на хаскеле для великого добра".

Учитывая эту функцию:

applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)

Автор использует это интересным способом:

ghci> applyTwice (++ [0]) [1]  
[1,0,0]
ghci> applyTwice ([0] ++) [1]
[0,0,1]

Здесь я ясно вижу, что полученная функция имела различные параметры, которые не были бы получены обычными средствами, учитывая, что это функция с карри (не так ли?). Итак, есть ли какой-то особый подход к разделу инфиксов от Haskell? Это универсально для всех инфиксных функций?


Как примечание, это моя первая неделя с Haskell и функциональным программированием, и я все еще читаю книгу.

3 ответа

Решение

Да, вы можете частично применить инфиксный оператор, указав его левый или правый операнд, просто оставив другой пустой (точно в двух написанных вами примерах).

Так, ([0] ++) такой же как (++) [0] или же \x -> [0] ++ x (помните, что вы можете превратить инфиксный оператор в стандартную функцию с помощью скобок), в то время как (++ [0]) равно \x -> x ++ [0],

Также полезно знать об использовании обратных галочек ( ``), которые позволяют превратить любую стандартную функцию с двумя аргументами в инфиксном операторе:

Prelude> elem 2 [1,2,3]
True
Prelude> 2 `elem` [1,2,3] -- this is the same as before
True
Prelude> let f = (`elem` [1,2,3]) -- partial application, second operand
Prelude> f 1
True
Prelude> f 4
False
Prelude> let g = (1 `elem`) -- partial application, first operand
Prelude> g [1,2]
True
Prelude> g [2,3]
False

Да, это синтаксис раздела на работе.

Разделы написаны как ( op e ) или же ( e op )где op - бинарный оператор, а e - выражение. Разделы - это удобный синтаксис для частичного применения бинарных операторов.

Следующие тождества имеют место:

(op e)  =   \ x -> x op e
(e op)  =   \ x -> e op x

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

(x + y) -> (+ y) -> (+)

Разделы (в основном, с некоторыми редкими угловыми случаями) рассматриваются как простые лямбды. (/ 2) такой же как:

\x -> (x / 2)

а также (2 /) такой же как \x -> (2 / x)для примера с некоммутативным оператором.

Там нет ничего глубоко интересного теоретически здесь происходит. Это просто синтаксический сахар для частичного применения инфиксных операторов. Это делает код немного красивее, часто. (Есть контрпримеры, конечно.)

Другие вопросы по тегам