Hindley-Milner型推論システムが機能し、再帰的レッツ(リンクされたコードではない)もサポートする小さなラムダ計算コンパイラーに取り組んでいます。これは、チューリングを完全にするのに十分であることを理解しています。
問題は、リストをサポートする方法がわからない、またはすでにリストをサポートしているかどうかわからないこと、そしてそれらをエンコードする方法を見つける必要があることだけです。型システムに新しいルールを追加する必要なく、それらを定義できるようにしたいと思います。
私はリストの考えることができる最も簡単な方法x
のいずれかであるものとしてあるnull
(または空のリスト)、またはANの両方が含まペアx
とのリストをx
。しかし、これを行うには、ペアとorを定義できる必要があります。
このようにペアを定義できるようです:
pair = λabf.fab
first = λp.p(λab.a)
second = λp.p(λab.b)
以来pair
タイプを持つことになりa -> (b -> ((a -> (b -> x)) -> x))
、通過した後、と言うint
とstring
、それはタイプで何かを得たい(int -> (string -> x)) -> x
のペアの表現であろう、int
とstring
。ここで私が気になるのは、それがペアを表す場合、なぜそれが論理的に等価ではなく、命題を意味しないのint and string
かということです。ただし、と同等(((int and string) -> x) -> x)
です。まるで、関数のパラメーターとして製品タイプしか持てないかのようです。この答えこの問題に対処しているようですが、彼が使用する記号の意味がわかりません。また、これが製品タイプを実際にエンコードしない場合、上記のペアの定義では実行できなかった製品タイプで実行できることはありますか(同じ方法でnタプルも定義できると考えて)?そうでない場合、これは含意のみを使用して(AFAIK)結合を表現できないという事実と矛盾しませんか?
また、合計タイプはどうですか?関数タイプのみを使用してなんとかしてエンコードできますか?もしそうなら、これはリストを定義するのに十分でしょうか?それとも、タイプシステムを拡張せずにリストを定義する他の方法はありますか?そうでない場合、できる限りシンプルにしたい場合、どのような変更を加える必要がありますか?
私はコンピュータープログラマーですが、コンピューターサイエンティストでも数学者でもないので、数学の表記を読むのはかなり苦手です。
編集: これまでに実装したものの技術的な名前はわかりませんが、基本的には、上でリンクしたコードのみです。これは、アプリケーション、抽象化、変数のルールを使用する制約生成アルゴリズムですHinley-Milnerアルゴリズムから、次に主要な型を取得する統合アルゴリズムから。例えば、式は\a.a
タイプが得られるa -> a
、と表現は、\a.(a a)
チェックエラーが発生したスローされます。これに加えて、let
ルールはありませんが、次の疑似コードのような再帰的なグローバル関数を定義できる同じ効果を持つように見える関数があります。
GetTypeOfGlobalFunction(term, globalScope, nameOfFunction)
{
// Here 'globalScope' contains a list of name-value pair where every value is of class 'ClosedType',
// meaning their type will be cloned before unified in the unification algorithm so that they can be used polymorphically
tempType = new TypeVariable() // Assign a dummy type to `tempType`, say, type 'x'.
// The next line creates an scope with everything in 'globalScope' plus the 'nameOfFunction = tempType' name-value pair
tempScope = new Scope(globalScope, nameOfFunction, tempType)
type = TypeOfTerm(term, tempScope) // Calculate the type of the term
Unify(tempType, type)
return type
// After returning, the code outside will create a 'ClosedType' using the returned type and add it to the global scope.
}
基本的に、コードは通常どおりに用語の型を取得しますが、統合する前に、ダミーの型で定義されている関数の名前を型スコープに追加して、それ自体から再帰的に使用できるようにします。
編集2:希望どおりのリストを定義するには、持っていない再帰型も必要になることに気づきました。
let func = \x -> (func x)
)を使用すると、私が持っているものを取得できるかどうかは確かです。