与lambda
在 lambda 演算中不同,您可以使用fun
OCaml 对 Church 数字进行编码。您将数字定义为接受一元函数(以s
“后继”命名)和基值(z
以“零”命名)的函数。例如,三是:
# let three = fun s z -> (s (s (s z)));;
val three : ('a -> 'a) -> 'a -> 'a = <fun>
如果您想将此表示转换为 OCaml 整数,请定义:
# let int_succ x = x + 1;;
然后你可以three
通过像这样调用它来获得 OCaml 整数表示:
# three int_succ 0;;
- : int = 3
它有效地依次调用int_succ
0、最里面的结果(即 1)等,直到你得到 3。
但是你可以在他们的教会代表中操纵这些数字,如下所示。例如,要计算任意流失数 n 的后继 Church 数:
# let succ n = fun s z -> (s (n s z));;
我们必须返回一个 Church 编号,结果是两个参数的函数,s
和z
。它也需要一个单一的输入,一个教堂号码n
。结果是呼唤s
,(n s z)
即数字的继任者n
。例如:
# (succ three) int_succ 0;;
- : int = 4
同样,我们可以定义add
:
# let add x y = (fun s z -> (x s (y s z)));;
val add : ('a -> 'b -> 'c) -> ('a -> 'd -> 'b) -> 'a -> 'd -> 'c = <fun>
在这里,该函数需要两个数字。该表达式(y s z)
表示对 number 进行的计算,在应用iny
时用作基值。如果将and 0 用于and ,您可以看到它将从 0 增加 编码 的次数,然后从该值增加 编码 的次数。x
(x s (y s z))
int_succ
s
z
(y s z)
y
x
例如:
# let two = fun s z -> (s (s z)) ;;
val two : ('a -> 'a) -> 'a -> 'a = <fun>
然后:
# let five = add two three;;
val five : ('_weak4 -> '_weak4) -> '_weak4 -> '_weak4 = <fun>
注意类型是弱的,你不需要太担心,但这意味着一旦你用给定的s
and调用了 5 z
,你将不能重用five
不同的类型。
# five int_succ 0;;
- : int = 5
现在,该类型已完全为人所知:
# five;;
- : (int -> int) -> int -> int = <fun>