機能は、多くの場合、固定小数点コンビネータに遭遇している期待される結果を得る:動的型付け言語のスキームでは、この関数を書くことができます。例えばY combinatorの1つの書式がλf.(λx.f (x x)) (λx.f (x x))
と書かれています。固定小数点コンビネータは、追加の再帰的な構造を持たないタイプ化されていないラムダ計算で一般的な再帰を実装するために使用され、これはタイプ変換されていないラムダ計算チューリング完了の一部です。
人々がラムダ計算の上にナイーブな静的型システムであるsimply-typed lambda calculusを開発したとき、彼らはもはやそのような関数を書くことができないことを発見しました。実際、単純型のラムダ計算では一般的な再帰を実行することはできません。したがって、単純型のラムダ計算はもはやチューリング完全ではない。 (一つの興味深い副作用は、単純に、型付きラムダ計算中のプログラムが常に終了するということです。)
、このような名前の再帰関数として内蔵された再帰的なメカニズムの問題を克服するために、標準的なMLの必要性、などの
実静的に型付けされたプログラミング言語( val rec
またはfun
)で定義され、再帰的なデータ型と呼ばれます。
再帰的データ型を使用して、必要なものをシミュレートすることは可能ですが、それほど美しくはありません。
基本的には、'a foo = 'a foo -> 'a
のようなタイプを定義します。ただし、これは許可されていません。代わりに、データ型でラップ:
datatype 'a foo = Wrap of ('a foo -> 'a);
fun unwrap (Wrap x) = x;
datatype 'a foo = Wrap of ('a foo -> 'a);
は基本的には、Wrap
とunwrap
は'a foo
と'a foo -> 'a
の間で変換するために使用され、その逆も同様です。
x x
の代わりに関数を呼び出す必要があるときはいつも、(unwrap x) x
(またはunwrap x x
)を明示的に記述する必要があります。すなわちunwrap
は、それを元の値に適用できる関数に変換します。
P.S.別のML言語OCamlには、再帰型(通常は無効)を有効にするオプションがあります。 -rectypes
フラグを持つインタプリタまたはコンパイラを実行すると、fun x -> x x
のようなものを書くことができます。基本的には、バックグラウンドでは、タイプチェッカーは、再帰型を「ラップ」および「アンラップ」してから挿入する必要がある場所を特定します。私は、同様の再帰型の機能を持つ標準的なML実装は認識していません。
誰かが興味があれば、これは[U Combinator(ページの一番下を見てください)](http://www.ucombinator.org/)と呼ばれていますが、それ以上のことは見つけられませんでした。 –
私はそれがUコンビネータと呼ばれていたのか分かりませんでしたが、そのページが示すように、私の答えに書かれているタイプのないラムダ計算の(終わりはない)プログラムを構築するのに使われています。 –