通过定义一个组合器,它:
被定义为没有自由变量的 lambda 项,因此根据定义,任何组合子都已经是 lambda 项,
例如,您可以通过以下方式定义列表结构:
Y = (list definition in lambda calculus)
Y LIST = (list definition in lambda calculus) LIST
Y LIST = (element insertion definition in lambda calculus)
直观地说,使用定点组合器,一个可能的定义是——考虑 \ = lambda:
- 一个列表要么是空的,后跟一个尾随元素,比如
0
;
- 或者一个列表由一个元素组成
x
,它可能是前一个列表中的另一个列表。
由于它是使用组合器(定点组合器)定义的,因此无需执行进一步的应用程序,以下抽象本身就是一个 lambda 术语。
Y = \f.\y.\x.f (x y)
现在,将其命名为 LIST:
Y LIST = (*\f*.\y.\x.*f* (x y)) *LIST* -- applying function name
LIST = \y.\x.LIST (x y), and adding the trailing element "0"
LIST = (\y.\x.LIST (x y) ) 0
LIST = (*\y*.\x.LIST (x *y*) ) *0*
LIST = \x.LIST (x 0), which defines the element insertion abstraction.
定点组合Y
器,或简单的组合器,允许您考虑 LIST 的定义已经是一个有效的成员,没有自由变量,因此不需要减少。
然后,您可以通过执行以下操作附加/插入元素,例如 1 和 2:
LIST = (\x.LIST (x 0)) 1 2 =
= (*\x*.LIST (*x* 0)) *1* 2 =
= (LIST (1 0)) 2 =
但是在这里,我们知道列表的定义,所以我们扩展它:
= (LIST (1 0)) 2 =
= ((\y.\x.LIST (x y)) (1 0)) 2 =
= ((*\y*.\x.LIST (x *y*)) *(1 0)*) 2 =
= ( \x.LIST (x (1 0)) ) 2 =
现在,插入 elemenet 2
:
= ( \x.LIST (x (1 0)) ) 2 =
= ( *\x*.LIST (*x* (1 0)) ) *2* =
= LIST (2 (1 0))
由于 LIST 是一个 lambda 术语,使用组合器定义,因此可以在新插入的情况下对其进行扩展,或者简单地保持原样。
为将来的插入扩展:
= LIST (2 (1 0)) =
= (\y.\x.LIST (x y)) (2 (1 0)) =
= (*\y*.\x.LIST (x *y*)) *(2 (1 0))* =
= \x.LIST (x (2 (1 0))) =
= ( \x.LIST (x (2 (1 0))) ) (new elements...)
我真的很高兴我能够自己推导出这个,但我很确定在定义堆栈、堆或一些更高级的结构时必须有一些很好的额外条件。
尝试导出堆栈插入/删除的抽象——没有所有的一步一步:
Y = \f.\y.\x.f (x y)
Y STACK 0 = \x.STACK (x 0)
STACK = \x.STACK (x 0)
为了对它执行操作,让我们命名一个空栈——分配一个变量(:
stack = \x.STACK (x 0)
// Insertion -- PUSH STACK VALUE -> STACK
PUSH = \s.\v.(s v)
stack = PUSH stack 1 =
= ( \s.\v.(s v) ) stack 1 =
= ( \v.(stack v) ) 1 =
= ( stack 1 ) = we already know the steps from here, which will give us:
= \x.STACK (x (1 0))
stack = PUSH stack 2 =
= ( \s.\v.(s v) ) stack 2 =
= ( stack 2 ) =
= \x.STACK x (2 (1 0))
stack = PUSH stack 3 =
= ( \s.\v.(s v) ) stack 3 =
= ( stack 3 ) =
= \x.STACK x (3 (2 (1 0)))
我们再次命名这个结果,以便我们弹出元素:
stack = \x.STACK x (3 (2 (1 0)))
// Removal -- POP STACK -> STACK
POP = \s.(\y.s (y (\t.\b.b)))
stack = POP stack =
= ( \s.(\y.s y (\t.\b.b)) ) stack =
= \y.(stack (y (\t.\b.b))) = but we know the exact expansion of "stack", so:
= \y.((\x.STACK x (3 (2 (1 0))) ) (y (\t.\b.b))) =
= \y.STACK y (\t.\b.b) (3 (2 (1 0))) = no problem if we rename y to x (:
= \x.STACK x (\t.\b.b) (3 (2 (1 0))) =
= \x.STACK x (\t.\b.b) (3 (2 (1 0))) = someone guide me here, if i'm wrong
= \x.STACK x (\b.b) (2 (1 0)) =
= \x.STACK x (2) (1 0) =
= \x.STACK x (2 (1 0))
为了什么,希望我们3
弹出了元素。
我试图自己推导出这个,所以,如果我没有遵循 lambda 演算有任何限制,请指出。