Encoding 接班人的麻烦&;莫根森的前身';s二进制编码

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

我想将二进制数添加到我的非类型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 (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
    ,如上所述
总之,你完全可以把Morgensen数字想象成列表上的左折(或右折,取决于你对列表的想象)


获取数字的
成功

获取一个数字的
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