回答:
Goの型推論に関するStackOverflowの回答をご覧ください。私はGoについてはあまり詳しくありませんが、この回答に基づくと、一方向の「型の推論」のように見えます(C ++の技術を借りる場合)。それはあなたが持っている場合、
x := y + z
次に、のタイプをx
計算することにより、のタイプが推定されy + z
ます。これは、コンパイラーにとって比較的簡単なことです。これを行うには、の種類y
とz
必要性は知られていることを演繹的に:これは、型注釈を介して行わまたはそれらに割り当てられたリテラルから推測することができます。
対照的に、ほとんどの関数型言語には、モジュール内のすべての可能な情報(または、推論アルゴリズムがローカルの場合は関数)を使用して変数の型を導出する型推論があります。複雑な推論アルゴリズム(Hindley-Milnerなど)は、多くの場合、舞台裏で何らかの形の型統一(方程式を解くのに少し似ています)を伴います。たとえば、Haskellで次のように記述したとします。
let x = y + z
その場合、Haskellはタイプを推測するだけでx
なくy
、z
単純に、それらを追加しているという事実に基づいて推測することもできます。この場合:
x :: Num a => a
y :: Num a => a
z :: Num a => a
(ここでの小文字a
は、C ++などの他の言語では「ジェネリック」と呼ばれることが多い多相型を示します。このNum a =>
部分は、型のサポートに何らかの加算の概念があることを示すための制約a
です。)
次に、より興味深い例を示します。再帰関数を定義できる固定小数点コンビネータです。
let fix f = f (fix f)
の型をどこにも指定してf
おらず、またの型も指定していないことに注意してください。ただしfix
、Haskellコンパイラは自動的に次のことを理解できます。
f :: t -> t
fix :: (t -> t) -> t
これはそれを言う:
f
は、任意の型t
から同じ型への関数でなければなりませんt
。fix
タイプのパラメータを受け取り、タイプt -> t
の結果を返す関数ですt
。Goの型推論は非常に制限されており、非常に単純です。1つの言語構成(変数宣言)でのみ機能し、右側の型を取り、左側の変数の型として使用します。
Haskellの型推論はどこでも使用でき、プログラム全体の型を推論するために使用できます。これは統一に基づいています。つまり、(概念的に)すべての型が「一度に」推論され、それらはすべて互いに影響を及ぼします。Goでは、型情報は変数宣言の右側から左側にのみ流れることができます。反対側、変数宣言の外側には絶対に置かないでください。Haskellでは、型情報はプログラム全体を通じてあらゆる方向に自由に流れます。
ただし、Haskellの型システムは非常に強力なので、型推論は実際に型の推論に失敗する可能性があります(より正確には、型を常に推論できるように制限を設ける必要があります)。Goの型システムは非常に単純(サブタイピングなし、パラメトリック多態性なし)であり、その推論は非常に制限されているため、常に成功します。
x
、y
、z
同じNum
、エリック・タイプではなく、彼らはまだすることができInteger
、S、Double
S、Ratio Integer
よ... Haskellは、他の型クラスのための数値型の間の任意の選択をするために喜んで、しかしではありません。