Encoding 接班人的麻烦&;莫根森的前身';s二进制编码
我想将二进制数添加到我的非类型lambda演算库中,但我一直使用Encoding 接班人的麻烦&;莫根森的前身';s二进制编码,encoding,functional-programming,binary,lambda-calculus,Encoding,Functional Programming,Binary,Lambda Calculus,我想将二进制数添加到我的非类型lambda演算库中,但我一直使用succ和pred函数。我使用的是a中概述的表示法,其中定义的大多数函数都起作用,succ和pred返回错误的结果 我很确定我的陈述是对的: dec bin De Bruijn classic 0 0 λλλ3 λa.λb.λc.a 1 1 λλλ13 λa.λb.λc.c a 2 10 λλλ2(13) λa.λb.λc.b
succ
和pred
函数。我使用的是a中概述的表示法,其中定义的大多数函数都起作用,succ
和pred
返回错误的结果
我很确定我的陈述是对的:
dec bin De Bruijn classic
0 0 λλλ3 λa.λb.λc.a
1 1 λλλ13 λa.λb.λc.c a
2 10 λλλ2(13) λa.λb.λc.b (c a)
3 11 λλλ1(13) λa.λb.λc.c (c a)
4 100 λλλ2(2(13)) λa.λb.λc.b (b (c a))
5 101 λλλ1(2(13)) λa.λb.λc.c (b (c a))
6 110 λλλ2(1(13)) λa.λb.λc.b (c (c a))
7 111 λλλ1(1(13)) λa.λb.λc.c (c (c a))
8 1000 λλλ2(2(2(13))) λa.λb.λc.b (b (b (c a)))
元组和投影看起来也不错:
tuple De Bruijn classic
[T, F] λ1(λλ2)(λλ1) λa.a (λb.λc.b) (λb.λc.c)
[T, F, F] λ1(λλ2)(λλ1)(λλ1) λa.a (λb.λc.b) (λb.λc.c) (λb.λc.c)
[T, F, F, T] λ1(λλ2)(λλ1)(λλ1)(λλ2) λa.a (λb.λc.b) (λb.λc.c) (λb.λc.c) (λb.λc.b)
πkn De Bruijn classic
π12 λ1(λλ2) λa.a (λb.λc.b)
π22 λ1(λλ1) λa.a (λb.λc.c)
使用0位(shl0
)和1位(shl1
)上移在测试中效果良好:
SHL0 ≡ λnbzo.z (n b z o) = λ λ λ λ 2 (4 3 2 1)
SHL1 ≡ λnbzo.o (n b z o) = λ λ λ λ 1 (4 3 2 1)
但是依赖于上述术语的succ
和pred
不:
SUCC ≡ λn.π22 (n Z A B) ≡ λ π22 (1 Z A B) where
Z ≡ [ZERO, ONE] // encoded like in the first piece of code
A ≡ λp.p (λnm.[SHL0 n, SHL1 n]) ≡ λ 1 (λ λ [SHL0 2, SHL1 2])
B ≡ λp.p (λnm.[SHL1 n, SHL0 m]) ≡ λ 1 (λ λ [SHL1 2, SHL0 1])
PRED ≡ λn.π22 (n Z A B) ≡ λ π22 (1 Z A B) where
Z ≡ [ZERO, ZERO] // encoded like in the first piece of code
A ≡ λp.p (λnm.[SHL0 n, SHL1 m]) ≡ λ 1 (λ λ [SHL0 2, SHL1 1])
B ≡ λp.p (λnm.[SHL1 n, SHL0 n]) ≡ λ 1 (λ λ [SHL1 2, SHL0 2])
示例结果:
succ 0 = λa.λb.λc.c a / λλλ13 ok
succ 1 = λa.λb.λc.b (b c) / λλλ2(21) wrong, expected λλλ2(13)
succ 2 = λa.λb.λc.c (b (c (λd.λe.λf.e (b d e f)) (λd.λe.λf.f (b d e f)))) / λλλ1(2(1(λλλ2(5321))(λλλ1(5321)))) wrong, expected λλλ1(13)
succ 3 = λa.λb.λc.b (b c) / λλλ2(21) wrong, expected λλλ2(2(13))
pred 1 = λa.λb.λc.b a / λλλ23 wrong-ish, expected λλλ3; it's just a leading zero, but it's stated that those should only be caused by inputs that are powers of 2
pred 2 = λa.λb.λc.c (b c) / λλλ1(21) wrong, expected λλλ13
pred 3 = λa.λb.λc.b (b a) / λλλ2(23) wrong, expected λλλ2(13)
pred 4 = λa.λb.λc.c (b c) / λλλ1(21) wrong, expected λλλ1(13)
我的术语评估器经过数百个术语的测试,所以我对它很有信心;我怀疑要么是我误读了什么,要么是什么印刷错误了。我遗漏了什么吗?因此,正如勒杰德兹提到的,我们设法让摩根森数字在单独的聊天中工作。在这个回答中,我将简单地描述它的一般工作原理 问题是:«我怀疑要么是我误读了什么,要么是什么印刷错误。我错过什么了吗?»
tl;博士:结果是一些与评估顺序有关的棘手问题导致了这个问题。问题中提到的摩根森数字起作用
详细回答:
succ
是如何工作的
注意:在下面的B中,N
始终假定为1
,如原稿所示
Morgensen数字背后的想法是让数字n=b\n。。。b_2 b_1
编码为\z.\x_0.\x_1。x{b_1}(x{b_2}(…(x{b_n}z)…)
。这是很难理解的,但如果这样说,它会变得更清晰:
数字n
是一个需要3个参数的术语,应用时返回x_{b_1}(x_{b_2}(…(x_{b_n})z)
那还不清楚。如果我们深入观察,我们会发现一个数字n
递归地应用于x_0
或x_1
,从一个术语z
开始。请注意,递归调用是“从左到右”进行的,即,如果我有一个编号b_n b_{n-1}。。。b_2 b_1
,然后按以下顺序计算递归调用:
- 首先,让它成为
i{n-1}
- 然后
,让它成为b{n-1}i{n-1}
i{n-2}
- 最后是我
与列表上的
折叠功能的关系
事实上,当我意识到这一点时,它只是让我想到了位列表的左折叠功能:假设你有一个位列表l=[b\n;…;b\u 2;b\u 1]
,那么你可以做以下事情:
fold_left (fun prev_acc -> fun b -> if b = 0 then x_0 prev_acc else x_1 prev_acc) z l
让f
fun prev_acc -> fun b -> if b = 0 then x_0 prev_acc else x_1 prev_acc
返回(根据)
评估结果如下:
计算结果为fzbn
,即x{bn}z
,如上所述i{n-1}
,如上所述fi{1}b_1
获取数字的
成功
获取一个数字的succ
就是获取n+1
。二进制增量是一个很好的属性:
如果m=bn。。。比比基比克。。。b1
,其中bj
是第一个0
(即bk=…=b1=1
),然后m+1=bn。。。BI10。。。0
这可以说明:
bn ... bi 0 1 1 1 1 1
如果我添加1
,那么我得到(通过详细说明所有步骤):
其中(1)tuple_msb
是包含(bn…bi,(bn…bi)+1)
的元组;其中(2)original_msb
和incr_msb
根据bj
计算。事实上:
- 如果
为bj
,则0
(bn…bibj)+1=(bn…bi0)+1=(bn…bi1)
- 如果
是bj
,则1
(bn…bi bj)+1=(bn…bi 1)+1=((bn…bi)+1)::0
fold_left
的完整功能如下:
(* We keep the original sequence on the left of the tuple, the incremented `bn ... bi bj` on the right *)
fun tuple_msb -> fun bj ->
if bj = 0 then
(tuple_msb._1 :: 0, tuple_msb._1 :: 1)
else
(tuple_msb._1 :: 1, tuple_msb._2 :: 0)
基本情况(即起始元素是元组(0,1)
)
从这里,我们很容易回到Morgensen不可读的术语(这里有一个关于参数顺序的隐藏的小捷径,但它真的不重要):
我们可以将fun tuple\u msb->(tuple\u msb.\u 1::0,tuple.\u 1::1)
识别为x\u 0
和fun tuple\u msb->(tuple\u msb.\u 1::1,tuple\u msb.\u 2::0)
根据我们在x\u 0
和x\u 1
开始时使用的符号,以及基本情况(即开始时的z
是(0,1)
)
为了得到最终的后继者,我们必须得到返回元组的正确部分,从而得到最终的结果
let succ n =
let ret_tuple = n z x_0 x_1 in
ret_tuple._2
或者用lambda术语:
succ' = λn. π22 (n z x_0 x_1)
所有的π22
,z
,x_0
和x_1
都有相应的定义
我们的
succ'
与提议的succ
有点不同,即x_0
不完全是a
,x_1
不完全是B
,但最后一步很简单,留给感兴趣的读者;-)当溴通知我他们对succ
的定义略有不同时,我将其移植到Ocaml+utop中,并使用我的库进行了测试。不过,它也失败了,所以我开始分析所有涉及的术语,结果发现所有内容都与我的实现中的内容几乎相同。我确信我的评估者都是可靠的,而且这些定义都是有效的,我一直在寻找,直到我找到了f
(* We keep the original sequence on the left of the tuple, the incremented `bn ... bi bj` on the right *)
fun tuple_msb -> fun bj ->
if bj = 0 then
(tuple_msb._1 :: 0, tuple_msb._1 :: 1)
else
(tuple_msb._1 :: 1, tuple_msb._2 :: 0)
let succ n =
let ret_tuple = n z x_0 x_1 in
ret_tuple._2
succ' = λn. π22 (n z x_0 x_1)
succ 1
= (λn.π² (n Z A B)) |1|
= (λn.π² (n Z A B)) (λz01.1 z)
= π² ((λz01.1 z) Z A B)
= π² (B Z)
= π² ((λp.p (λnm.[↑1 n, ↑0 m])) [|0|, |1|])
= π² ([|0|, |1|] (λnm.[↑1 n, ↑0 m]))
= π² ((λx.x |0| |1|) (λnm.[↑1 n, ↑0 m]))
= π² ((λnm.[↑1 n, ↑0 m]) |0| |1|)
= π² [↑1 |0|, ↑0 |1|]
= ↑0 |1|
= (λn.λz01.0 (n z 0 1)) |1|
= λz01.0 (|1| z 0 1)
= λz01.0 ((λz01.1 z) z 0 1)
= λz01.0 (1 z)
= |2|
(λ(λ1(λλ1))(1(λ1(λλλ3)(λλλ13))(λ1(λλλ1((λλλλ2(4321))2)((λλλλ1(4321))2)))(λ1(λλλ1((λλλλ1(4321))2)((λλλλ2(4321))1)))))(λλλ13)
(λ(λ1(λλ1))(1(λ1(λλλ3)(λλλ13))(λ1(λλλ1((λλλλ2(4321))2)((λλλλ1(4321))2)))(λ1(λλλ1((λλλλ1(4321))2)((λλλλ2(4321))1)))))(λλλ13)
^ ^ ^^^^^^^
↳ becomes λλλ13
(λ1(λλ1))((λλλ13)(λ1(λλλ3)(λλλ13))(λ1(λλλ1((λλλλ2(4321))2)((λλλλ1(4321))2)))(λ1(λλλ1((λλλλ1(4321))2)((λλλλ2(4321))1))))
^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
↳ becomes (λλλ13)(λ1(λλλ3)(λλλ13))(λ1(λλλ1((λλλλ2(4321))2)((λλλλ1(4321))2)))(λ1(λλλ1((λλλλ1(4321))2)((λλλλ2(4321))1)))
(λλλ13)(λ1(λλλ3)(λλλ13))(λ1(λλλ1((λλλλ2(4321))2)((λλλλ1(4321))2)))(λ1(λλλ1((λλλλ1(4321))2)((λλλλ2(4321))1)))(λλ1)
^ ^ ^^^^^^^^^^^^^^^^^
↳ becomes λ1(λλλ3)(λλλ13)
(λλ1(λ1(λλλ3)(λλλ13)))(λ1(λλλ1((λλλλ2(4321))2)((λλλλ1(4321))2)))(λ1(λλλ1((λλλλ1(4321))2)((λλλλ2(4321))1)))(λλ1)
^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - is dropped
(λ1(λ1(λλλ3)(λλλ13)))(λ1(λλλ1((λλλλ1(4321))2)((λλλλ2(4321))1)))(λλ1)
^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
↳ becomes λ1(λλλ1((λλλλ1(4321))2)((λλλλ2(4321))1))
(λ1(λλλ1((λλλλ1(4321))2)((λλλλ2(4321))1)))(λ1(λλλ3)(λλλ13))(λλ1)
^^ ^^^^^^^^^^^^^^^^^
↳ becomes λ1(λλλ3)(λλλ13)
(λ1(λλλ3)(λλλ13))(λλλ1((λλλλ1(4321))2)((λλλλ2(4321))1))(λλ1)
^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
↳ becomes λλλ1((λλλλ1(4321))2)((λλλλ2(4321))1)
(λλλ1((λλλλ1(4321))2)((λλλλ2(4321))1))(λλλ3)(λλλ13)(λλ1)
^ ^^^^^^ - is dropped
(λλ1((λλλλ1(4321))2)((λλλλ2(4321))1))(λλλ13)(λλ1)
^ ^ ^^^^^^^
↳ becomes λλλ13
(λ1((λλλλ1(4321))(λλλ13))((λλλλ2(4321))1))(λλ1)
^^ ^
↳ becomes (λλ1) ↳ becomes (λλ1)
(λλ1)((λλλλ1(4321))(λλλ13))((λλλλ2(4321))(λλ1))
^ ^^^^^^^^^^^^^^^^^^^^^^ - is dropped
(λ1)((λλλλ2(4321))(λλ1))
^^ ^^^^^^^^^^^^^^^^^^^^
↳ becomes (λλλλ2(4321))(λλ1)
(λλλλ2(4321))(λλ1)
^ ^ ^^^^^
↳ becomes λλ1
λλλ2((λλ1)321)
^ ^ - is dropped
λλλ2((λ1)21)
^^ ^
↳ becomes 2
λλλ2(21) // fail
(λ(λ1(λλ1))(1(λ1(λλλ3)(λλλ13))(λ1(λλ(λλλ132)((λλλλ2(4321))2)((λλλλ1(4321))2)))(λ1(λλ(λλλ132)((λλλλ1(4321))2)((λλλλ2(4321))1)))))(λλλ13)
(λ(λ1(λλ1))(1(λ1(λλλ3)(λλλ13))(λ1(λλ(λλλ132)((λλλλ2(4321))2)((λλλλ1(4321))2)))(λ1(λλ(λλλ132)((λλλλ1(4321))2)((λλλλ2(4321))1)))))(λλλ13)
^ ^ ^^^^^^^
↳ becomes λλλ13
(λ1(λλ1))((λλλ13)(λ1(λλλ3)(λλλ13))(λ1(λλ(λλλ132)((λλλλ2(4321))2)((λλλλ1(4321))2)))(λ1(λλ(λλλ132)((λλλλ1(4321))2)((λλλλ2(4321))1))))
^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
↳ becomes (λλλ13)(λ1(λλλ3)(λλλ13))(λ1(λλ(λλλ132)((λλλλ2(4321))2)((λλλλ1(4321))2)))(λ1(λλ(λλλ132)((λλλλ1(4321))2)((λλλλ2(4321))1)))
(λλλ13)(λ1(λλλ3)(λλλ13))(λ1(λλ(λλλ132)((λλλλ2(4321))2)((λλλλ1(4321))2)))(λ1(λλ(λλλ132)((λλλλ1(4321))2)((λλλλ2(4321))1)))(λλ1)
^ ^ ^^^^^^^^^^^^^^^^^
↳ becomes λ1(λλλ3)(λλλ13)
(λλ1(λ1(λλλ3)(λλλ13)))(λ1(λλ(λλλ132)((λλλλ2(4321))2)((λλλλ1(4321))2)))(λ1(λλ(λλλ132)((λλλλ1(4321))2)((λλλλ2(4321))1)))(λλ1)
^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - is dropped
(λ1(λ1(λλλ3)(λλλ13)))(λ1(λλ(λλλ132)((λλλλ1(4321))2)((λλλλ2(4321))1)))(λλ1)
^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
↳ becomes λ1(λλ(λλλ132)((λλλλ1(4321))2)((λλλλ2(4321))1))
(λ1(λλ(λλλ132)((λλλλ1(4321))2)((λλλλ2(4321))1)))(λ1(λλλ3)(λλλ13))(λλ1)
^^ ^^^^^^^^^^^^^^^^^
↳ becomes λ1(λλλ3)(λλλ13)
(λ1(λλλ3)(λλλ13))(λλ(λλλ132)((λλλλ1(4321))2)((λλλλ2(4321))1))(λλ1)
^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
↳ becomes λλ(λλλ132)((λλλλ1(4321))2)((λλλλ2(4321))1)
(λλ(λλλ132)((λλλλ1(4321))2)((λλλλ2(4321))1))(λλλ3)(λλλ13)(λλ1)
^ ^ ^^^^^^
↳ becomes λλλ3
(λ(λλλ132)((λλλλ1(4321))(λλλ3))((λλλλ2(4321))1))(λλλ13)(λλ1)
^ ^ ^^^^^^^
↳ becomes λλλ13
(λλλ132)((λλλλ1(4321))(λλλ3))((λλλλ2(4321))(λλλ13))(λλ1)
^ ^ ^^^^^^^^^^^^^^^^^^^^^
↳ becomes (λλλλ1(4321))(λλλ3)
(λλ1((λλλλ1(4321))(λλλ3))2)((λλλλ2(4321))(λλλ13))(λλ1)
^ ^ ^^^^^^^^^^^^^^^^^^^^^^
↳ becomes (λλλλ2(4321))(λλλ13)
(λ1((λλλλ1(4321))(λλλ3))((λλλλ2(4321))(λλλ13)))(λλ1)
^^ ^^^^^
↳ becomes λλ1
(λλ1)((λλλλ1(4321))(λλλ3))((λλλλ2(4321))(λλλ13))
^ ^^^^^^^^^^^^^^^^^^^^^ - is dropped
(λ1)((λλλλ2(4321))(λλλ13))
^^ ^^^^^^^^^^^^^^^^^^^^^^
↳ becomes (λλλλ2(4321))(λλλ13)
(λλλλ2(4321))(λλλ13)
^ ^ ^^^^^^^
↳ becomes λλλ13
λλλ2((λλλ13)321)
^ ^ ^
↳ becomes the right-hand side 3 and gets an index upgrade due to extra abstractions
λλλ2((λλ15)21)
^ ^
↳ gets its index downgraded
λλλ2((λ14)1)
^^ ^
↳ becomes the right-hand side 1; 4 gets an index downgrade
λλλ2(13) // aww yiss
(λλλ1((λλλλ1(4321))2)((λλλλ2(4321))1))(λλλ3)(λλλ13)(λλ1) // normalized tuple
^ ^^^^^^ - is dropped
(λλ(λλλ132)((λλλλ1(4321))2)((λλλλ2(4321))1))(λλλ3)(λλλ13)(λλ1) // unnormalized tuple
^ ^ ^^^^^^
↳ becomes λλλ3
λ PI22 (1 [ZERO, ONE] (λ 1 (λ λ [SHL0 2, SHL1 2])) (λ 1 (λ λ [SHL1 2, SHL0 1]))) // wrong
λ PI22 (1 [ZERO, ONE] (λ 1 (λ λ TUPLE2 (SHL0 2) (SHL1 2))) (λ 1 (λ λ TUPLE2 (SHL1 2) (SHL0 1)))) // right
where TUPLE2 ≡ λ λ λ 1 3 2