Подтвердить что ты не робот

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

Хотя я немного понимаю о каррировании в математическом смысле, частично применение функции infix было новой концепцией, которую я обнаружил после дайвинга в книгу Учите вас в Haskell для Great Good.

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

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? Является ли это общим для всех функций infix?


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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

(x + y)(+ y)(+)

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

\x -> (x / 2)

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

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