Частичное приложение с функциями 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 и функциональное программирование,
и я все еще читаю книгу.
Ответы
Ответ 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)
для примера с некоммутативным оператором.
Здесь нет ничего интересного, теоретически идущего здесь. Это просто синтаксический сахар для частичного применения инфиксных операторов. Это делает код немного красивее, часто. (Конечно, есть контрпримеры.)