Цитата Википедии:
Комбинатор - это функция высшего порядка, которая использует только приложение-функцию и ранее определенные комбинаторы для определения результата из своих аргументов.
Теперь, что это значит? Это означает, что комбинатор - это функция (вывод определяется исключительно ее вводом), чей ввод включает функцию в качестве аргумента.
Как выглядят такие функции и для чего они используются? Вот несколько примеров:
(f o g)(x) = f(g(x))
Здесь o
- комбинатор, который принимает 2 функции, f
и g
, и возвращает в качестве результата функцию, составленную из f
с g
, а именно f o g
.
Комбинаторы могут использоваться для сокрытия логики. Скажем, у нас есть тип данных NumberUndefined
, где NumberUndefined
может принимать числовое значение Num x
или значение Undefined
, где x
a - Number
. Теперь мы хотим построить сложение, вычитание, умножение и деление для этого нового числового типа. Семантика та же, что и для Number
, за исключением того, что Undefined
является входом, выход также должен быть Undefined
, а при делении на число 0
выход также Undefined
.
Можно написать утомительный код, как показано ниже:
Undefined +' num = Undefined
num +' Undefined = Undefined
(Num x) +' (Num y) = Num (x + y)
Undefined -' num = Undefined
num -' Undefined = Undefined
(Num x) -' (Num y) = Num (x - y)
Undefined *' num = Undefined
num *' Undefined = Undefined
(Num x) *' (Num y) = Num (x * y)
Undefined /' num = Undefined
num /' Undefined = Undefined
(Num x) /' (Num y) = if y == 0 then Undefined else Num (x / y)
Обратите внимание, что все они имеют одинаковую логику относительно Undefined
входных значений. Только деление делает немного больше. Решение состоит в том, чтобы извлечь логику, сделав ее комбинатором.
comb (~) Undefined num = Undefined
comb (~) num Undefined = Undefined
comb (~) (Num x) (Num y) = Num (x ~ y)
x +' y = comb (+) x y
x -' y = comb (-) x y
x *' y = comb (*) x y
x /' y = if y == Num 0 then Undefined else comb (/) x y
Это можно обобщить в так называемую монаду Maybe
, которую программисты используют в функциональных языках, таких как Haskell, но я не буду туда идти.