コンビネータを定義することにより、次のようになります。
は自由変数のないラムダ項として定義されているため、定義上、任意のコンビネータはすでにラムダ項です。
たとえば、次のように記述して、リスト構造を定義できます。
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
ます。これは、前のリスト内の別のリストである可能性があります。
コンビネータ(固定小数点コンビネータ)で定義されているため、さらにアプリケーションを実行する必要はありません。次の抽象化は、ラムダ用語そのものです。
Y = \f.\y.\x.f (x y)
今、それをリストと名付けます:
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はコンビネータで定義されたラムダ項であるため、新しい挿入の場合は拡張することも、そのままにしておくこともできます。
将来の挿入のために拡張:
= 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
がポップされます。
私はこれを自分で導き出そうとしたので、私が従わなかったラムダ計算からの制限がある場合は、それを指摘してください。