ゼロの教会数字から始めましょう。
λf.λx. x : β → α → α
一部だけを見るとλf.λx.
、引数が 2 つの関数があると推測できます。したがって、その型はα → β → γ
であり、α
とβ
は引数の型をγ
表し、結果の型を表します。ここで、本体x
は型をさらに制約します。関数の戻り値の型は、2 番目の引数の型と同じでなければなりません。その結果α → β → β
、または名前を変更した後 (α ↔ β):になりλf.λx. x : β → α → α
ます。f
関数であるという事実を使用しなかったため、これがゼロの最も一般的な型です。実際、型指定されていないラムダ計算のチャーチゼロ数値は気にしません。最初の引数であることを忘れているだけです。β
は単なるプレースホルダーであるため、特殊化することができますα → α
、これにより、ゼロのより具体的な型が得られます -- λf.λx. x : (α → α) → α → α
。
見てみましょう1
:
λf.λx. f x : (α → β) → α → β
繰り返しますが、これは 2 引数の関数です:α → β → γ
ですが、今回は ( の本体を見てください) 最初の引数が関数であることが1
わかっているため、 :を置き換える必要がある型があります。これで、 に適用できなければならないことがわかりました。これは、 の型との引数の型が等しくなければならないことを意味します: = 、したがって、 に到達しました。しかし、私たちが知っているのはそれだけではなく、typeを持ち、数値が returnであり、この情報を適用すると=が得られます。これらすべてを組み込むと、または名前を変更した後に到達します。f
f
δ → ε
α
(δ → ε) → β → γ
f
x
x
f
δ
β
(β → ε) → β → γ
f x
ε
f x
ε
γ
(β → γ) → β → γ
λf.λx. f x : (α → β) → α → β
. ここでも、使用目的に関する情報は使用しませんでした。そのため、最も一般的な型を取得しました。もちろん、(制限β
=によってα
) に特殊化できますλf.λx. f x : (α → α) → α → α
。
2
今度は さんの番です:
λf.λx. f (f x) : (α → α) → α → α
今回はすべての手順を繰り返すわけではありませんが、(中間の手順として) に到達できますλf.λx. f (f x) : (α → β) → α → β
。ただし、今回はf
の結果をそれ自体にフィードしていることに注意してください: f (f x)
。これは、f
の入力と出力の型が等しくなければならないことを意味し、つまりβ
=であり、今回α
は最も一般的な型です。λf.λx. f (f x) : (α → α) → α → α
(*) Church の 、 などは、最も一般的な型と同じであることに注意してください3
。4
これは2
、複数の関数を適用しても型をさらに特殊化するための追加情報が得られないためです。
加算関数についてはλm.λn.λf.λx. m f (n f x)
、もう少し簡潔に説明します。
- 式の型が であると仮定します
α → β → γ → δ → ε
。
m
は 2 つの引数の関数です:α
に制限する必要がありますα' → α'' → α'''
- についても同じ
n
:β
に制限する必要がありますβ' → β'' → β'''
m
とn
の最初の引数は同じ型で、次の型ですf
: α'
= β'
=γ
n
の 2 番目の引数の型はδ
n
m
の結果の型がの 2 番目の引数の型と等しい: β'''
=α''
- 上記のすべての知識を組み合わせてみましょう
n : γ → δ → α''
- 同じ
m : γ → α'' → ε
- したがって、結果の型は
(γ → α'' → ε) → (γ → δ → α'') → γ → δ → ε
変数の名前を変更して、見栄えを良くしましょう。
の最も一般的なタイプλm.λn.λf.λx. m f (n f x)
は
(β → γ → ε) → (β → α → γ) → β → α → ε
.
β
教会の数字 ( = α → α
、γ
= α
、ε
= α
)の二項演算であると予想されるものに特化できることを確認しましょう。
((α → α) → α → α) → ((α → α) → α → α) → (α → α) → α → α
.