Примеры комбинаторов

Мы разобрали три комбинатора неподвижной точки — Карри, Тьюринга и Z — и пора сказать, что вообще такое комбинатор. Комбинатор — это замкнутый λ-терм, без свободных переменных: он ничего не берёт из окружения, а только тасует и склеивает собственные аргументы. Таких термов множество, мы посмотрим наиболее часто встречаемые:

  • I=λx.x\mathrm{I} = \lambda x.\,x — тождество: отдаёт аргумент как есть.
  • K=λxy.x\mathrm{K} = \lambda x\,y.\,x — константа: берёт первый аргумент, второй отбрасывает.
  • S=λfgx.fx(gx)\mathrm{S} = \lambda f\,g\,x.\,f\,x\,(g\,x) — подстановка: раздаёт xx и в ff, и в gg, затем применяет одно к другому.
  • B=λfgx.f(gx)\mathrm{B} = \lambda f\,g\,x.\,f\,(g\,x) — композиция: прогоняет xx через gg, потом через ff.
  • C=λfxy.fyx\mathrm{C} = \lambda f\,x\,y.\,f\,y\,x — перестановка: меняет местами два аргумента.
  • W=λfx.fxx\mathrm{W} = \lambda f\,x.\,f\,x\,x — удвоение: скармливает xx функции дважды.

На Haskell комбинаторы выглядят так:

id 5             -- => 5            (I)
const 1 2        -- => 1            (K)
ap (+) (*2) 3    -- => 9  = 3 + 3*2 (S)
((+1) . (*2)) 3  -- => 7  = 3*2 + 1 (B)
flip (-) 3 10    -- => 7  = 10 - 3  (C)
join (*) 4       -- => 16 = 4*4     (W)