すべての新しいプログラミング言語、または少なくとも一般的に使用されている型推論が使用されているようです。 Javascriptでさえ、さまざまな実装(Acscript、TypeScriptなど)を通じて型と型推論を得ました。それは私には素晴らしく見えますが、トレードオフがあるのか、なぜJavaまたは古い良い言語に型推論がないのか)と思いますか?
Haskellの型システムは完全に推論可能です(多態的な再帰、特定の languageextensions 、および恐ろしい monomorphism制限 を除いて)、それでもプログラマーはまだ頻繁に型を提供しています必要がない場合でも、ソースコードの注釈。どうして?
map :: (a -> b) -> [a] -> [b]
です。より一般的な形式(fmap :: Functor f => (a -> b) -> f a -> f b
)は、リストだけでなく、すべてのFunctor
sに適用されます。しかし、map
は初心者には理解しやすいと感じられたため、兄と一緒に暮らしています。全体として、静的に型付けされているものの、エラーが発生しないシステムの欠点は、一般に静的型付けの欠点とほとんど同じです。このサイトなどでよく使われているディスカッション(「静的型付けの欠点」をググると、何百もの問題が発生します。炎の戦争のページの)。もちろん、上記の欠点のいくつかは、推論可能なシステムにおけるより少ない量の型注釈によって改善されます。さらに、型推論には独自の利点があります。 ホール駆動型開発 は型推論なしでは実現できません。
Java *は、あまりにも多くの型注釈を必要とする言語が煩わしいことを証明しますが、少なすぎると、上記で説明した利点を失うことになります。オプトアウト型の推論を使用する言語は、2つの極端な方法のバランスが取れています。
*素晴らしいスケープゴートであるJavaでも、一定量のlocal型推論を実行します。 Map<String, Integer> = new HashMap<>();
のようなステートメントでは、コンストラクターのジェネリック型を指定する必要はありません。一方、MLスタイルの言語は通常globally推論可能です。
C#では、型推論はコンパイル時に行われるため、実行時のコストはゼロです。
スタイルの問題として、var
は、タイプを手動で指定することが不便または不必要な状況で使用されます。 Linqはそのような状況の1つです。もう一つは:
var s = new SomeReallyLongTypeNameWith<Several, Type, Parameters>(andFormal, parameters);
これがないと、単にvar
と言うのではなく、本当に長い型名(および型パラメーター)を繰り返すことになります。
明示的である場合は、型の実際の名前を使用して、コードの明確性を向上させます。
値が構築時に設定されるメンバー変数宣言など、型推論を使用できない状況や、インテリセンスを正しく機能させたい場合があります(HackerrankのIDEはインテリセンスを行いません)型を明示的に宣言しない限り、変数のメンバー)。
良い質問!
そして、明示的な型注釈なしに奇妙なことをすることができないより難解な言語があります。これまでのところ、私が知っている一般的/人気/将来性があることを除いて、言及するのに十分有望なものはありません。
それは私には素晴らしく見えますが、トレードオフがあるのか、なぜJavaまたは古い良い言語に型推論がないのか)と思いますか?
ここでのルールではなく、Javaが例外です。 C++(私が信じるのは「古き良き言語」と見なされます:)ですら、C++ 11標準以降、auto
キーワードを使用した型推論をサポートしています。変数の宣言だけでなく、関数の戻り値の型としても機能します。これは、一部の複雑なテンプレート関数で特に便利です。
暗黙的な型付けと型推論には多くの優れたユースケースがあり、実際に実行してはいけないユースケースもあります。これは時々好みの問題であり、議論の対象でもあります。
しかし、間違いなく優れたユースケースがあることは、それ自体が言語がそれを実装する正当な理由です。また、この機能の実装は難しくなく、実行時のペナルティはなく、コンパイル時間にも大きな影響はありません。
開発者に型推論を使用する機会を与えることには、実際の欠点はありません。
一部の回答者は、明示的な型付けが時々どのように良いかを推論し、それらは確かに正しいです。しかし、暗黙の型付けをサポートしないことは、言語が常に明示的な型付けを強制することを意味します。
したがって、本当の欠点は、言語しないが暗黙の型付けをサポートする場合です。これにより、開発者がそれを使用する正当な理由がないことが示されます。
Hindley-Milner型推論システムとGoスタイル型推論の主な違いは、情報フローの方向です。 HMでは、型情報は、統一を介して前後に流れます。 Goでは、タイプ情報は転送のみを転送します。転送置換のみを計算します。
HMの型推論は、ポリモーフィックに型付けされた関数型言語でうまく機能する素晴らしい革新ですが、Goの作者は、多すぎることを試みているとおそらく主張します。
情報が順方向と逆方向の両方に流れるという事実は、HMタイプの推論が非常に非局所的な問題であることを意味します。型注釈がない場合、プログラム内のすべてのコード行が1行のコードの入力に影響している可能性があります。前方置換のみしかない場合は、型エラーの原因がエラーの前のコードにある必要があることがわかります。後に続くコードではありません。
HMの型推論では、constraintsで考える傾向があります。型を使用する場合、その型に可能な型を制限します。結局、完全に制約されないままになっているタイプ変数があるかもしれません。 HMタイプ推論の洞察は、これらのタイプは実際には重要ではないため、それらは多態変数に変換されます。ただし、この余分な多型は、いくつかの理由で望ましくない場合があります。最初に、一部の人々が指摘したように、この余分なポリモーフィズムは望ましくない可能性があります。HMが一部の偽のコードの偽の多形型を結論付け、後で奇妙なエラーを引き起こす。次に、型がポリモーフィックのままになっていると、実行時の動作に影響を与える可能性があります。たとえば、過度に多態的な中間結果が 'showの理由です。 「読む」はHaskellではあいまいと見なされます。別の例として、ポリモーフィック値は、それらが評価されるタイプごとに複数回評価されなければならず、単相性の制限が動機付けられます。