F#でrecキーワードが必要なのはなぜですか?


28

F#では、recキーワードを使用する必要があります。Haskellでは、特定の関数が再帰的であるかどうかを明示的に伝える必要はありません。

関数型プログラミングにおける再帰の役割を考えると、F#の設計はかなり奇妙に思えます。それは良い言語設計の決定ですか、それとも歴史的な理由または実装の制約のためにのみ存在しますか?

回答:


16

HaskellとF#のセマンティクスには固有の違いがあります。Haskellでは、関数呼び出しは実際の計算を実行しませんが、「サンク」として知られるヒープオブジェクトを割り当てます。サンクが自分自身または別のサンクへのリンクを持っていることはまったく問題ありません。しかし、F#で、関数呼び出しのような表現を作り、実際の呼び出しでlet x = 1 : 2 : x in x無効に-それが必要とするx前に構築することが1 : 2 : x構築されます。ただし、無限リストの定義は多かれ少なかれ合理的であり、定義する何らかの方法が存在する必要があります。ここにのルーツがありrecます。さらに知りたい場合は、SMLおよびHaskellの操作上のセマンティクスを検索して読んでください。これは異なります。


2
知る限り、Haskellには意図的に操作上のセマンティクスがありません。
dan_waterworth

@dan_waterworthでは、動作セマンティクスが定義されていないとコンパイルできません。
-permeakra

8
Haskell言語は、操作上のセマンティクスを定義しませんが、代わりに表示的なセマンティクスを提供します。コンパイラを構築すると、操作上のセマンティクスが暗黙的に定義されますが、これはHaskell言語標準の一部であることを意味するものではありません。
dan_waterworth

6
@dan_waterworth実際には、Haskell言語の実装と標準はghcだけであり、Fc標準も1つしかありません。Microsoftによる実装です。理論的にはあなたは正しいかもしれませんが、練習はまったく別物です。
-permeakra

19

この質問はSO回答されており、「rec」が使用される理由についての強力な歴史的背景が含まれています。

後世の重要な引用は次のとおりです。

フランス語のCAMLファミリーの言語(OCamlを含む)では、関数はデフォルトでは再帰的ではありません。この選択により、新しい定義の本体内で以前の定義を参照できるため、これらの言語のletを使用して関数(および変数)定義を簡単に置き換えることができます。F#はこの構文をOCamlから継承しました。


12

再帰letは、通常の意味よりもかなり複雑な意味を定義します。そのため、シンプルでクリーンな言語設計のために、両方の、別々の持つものとしてちょうど同じ持っている良い理由があるletlet*letrecのスキームでは。

Simpleはとlet x = y in z同等((fun x -> z) y)です。再帰的なletははるかに複雑で、固定小数点コンビネーターの使用を伴う場合があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.