私は、連結言語用のコンパイラに取り組んでおり、型推論のサポートを追加したいと考えています。Hindley–Milnerは理解していますが、型理論を学んでいるので、それをどのように適応させるかわかりません。次のシステムは健全で、決定的に推測できますか?
用語は、リテラル、用語の構成、用語の引用、またはプリミティブです。
すべての用語は関数を示します。2つの関数およびe 2の場合、e 1並置が逆組成を示しています。リテラルはニラディック関数を示します。
構成以外の用語には、基本的なタイプルールがあります。
連結言語にはアプリケーションルールがないため、アプリケーションのルールは特にありません。
型は、リテラル、型変数、またはスタックからスタックへの関数のいずれかです。ここで、スタックは右ネストされたタプルとして定義されます。すべての関数は、「残りのスタック」に関して暗黙的にポリモーフィックです。
これが疑わしいと思われる最初のことですが、何が問題なのか正確にはわかりません。
読みやすくし、かっこを減らすために型スキームではb = b × (a )。また、単一の値ではなく、スタックを示す変数に大文字を使用します。
6つのプリミティブがあります。最初の5つはかなり無害です。dup
最上位の値を取り、その2つのコピーを生成します。swap
上位2つの値の順序を変更します。pop
トップ値を破棄します。quote
値を取り、それを返す引用(関数)を生成します。apply
スタックに引用を適用します。
最後のcompose
結合子、は2つの引用符を取り、それらの連結のタイプ、つまり[ e 1 ]を返す必要があります。静的に型付けされた連結言語Catでは、型は非常に簡単です。compose
ただし、このタイプは制限が厳しすぎます。最初の関数の生成が2番目の関数の消費と正確に一致する必要があります。実際には、異なるタイプを想定してから、それらを統一する必要があります。しかし、そのタイプをどのように書くでしょうか?
あなたが聞かせている場合意味の違いの2種類を、私は考えてあなたがの種類書くことができ、正しくを。compose
これはまだ比較的簡単です。compose
関数と1つのf 2:D → Eを取ります。その結果、消費Bを消費頂上F 2によって生成されていないF 1、及び生成Dをの生産頂上fは1で消費されないF 2。これにより、通常の構成の規則が与えられます。
しかし、この仮想的な実際に何かに対応していることは知りません。タプルの単純な違いでしょうか?
Is there something horribly broken about this that I’m not seeing, or am I on something like the right track? (I’ve probably quantified some of this stuff wrongly and would appreciate fixes in that area as well.)
compose
is too restrictive? I have the impression that this is fine like this. (e.g. the restriction could be handled by unification like for application in like in the λ-calculus)
twice
defined as dup compose apply
, which takes a quotation and applies it twice. [1 +] twice
is fine: you’re composing two functions of type . But [pop] twice
is not: if , the problem is that , so the expression is disallowed even though it ought to be valid and have type . The solution is of course to put the qualifier in the right place, but I’m mainly wondering how to actually write the type of compose
without some circular definition.