Scala の型システムは Java の相互運用性によって弱められているため、Haskell の型システムと同じ機能を実行できないと読んだことがあります。これは本当ですか?弱点は型消去によるものですか、それとも私はあらゆる点で間違っていますか? この違いが Scala に型クラスがない理由ですか?
6 に答える
大きな違いは、Scala には Hindley-Milner グローバル型推論がなく、代わりにローカル型推論の形式を使用するため、メソッド パラメーターの型と、オーバーロードされた関数または再帰関数の戻り値の型を指定する必要があることです。
これは、タイプの消去や JVM のその他の要件によって引き起こされるものではありません。ここで考えられるすべての困難は克服することができます。
HM 推論は、オブジェクト指向のコンテキストでは機能しません。具体的には、型ポリモーフィズムが使用される場合 (型クラスのアドホック ポリモーフィズムとは対照的に)。これは、他の Java ライブラリとの強力な相互運用性、および (それほどではありませんが) JVM から最適な最適化を得るために重要です。
Haskell または Scala のどちらかがより強力な型システムを持っていると述べるのは、実際には有効ではありません。単にそれらが異なるというだけです。どちらの言語も、型ベース プログラミングの限界をさまざまな方向に押し広げており、それぞれの言語には、他の言語では真似できない独自の強みがあります。
Scala の型システムは Haskell の型システムとは異なりますが、Scala の概念は、Haskell の強みと、研究者や専門家の知識豊富なコミュニティから直接影響を受けることがあります。
もちろん、そもそも関数型プログラミングを主な目的としていない VM で実行すると、このプラットフォームを対象とする既存の言語との互換性に関する懸念が生じます。型に関する推論のほとんどはコンパイル時に行われるため、実行時の Java の (言語およびプラットフォームとしての) 制限は心配する必要はありません (型の消去を除いて。エコシステムをよりシームレスに)。
私の知る限り、Java の型システム レベルでの唯一の「妥協点」は、生の型を処理するための特別な構文です。Scala は生の型を許可しなくなりましたが、そのバグを含む古い Java クラス ファイルを受け入れます。List[_]
のようなコード(またはより長い同等のコード) を見たことがあるかもしれませんList[T] forSome { type T }
。これは Java との互換性機能ですが、内部的にも存在型として扱われ、型システムを弱めることはありません。
Scala の型システムは型クラスをサポートしていますが、Haskell よりも冗長な方法です。Scala の型システムの相対的な強さについて別の印象を与えるかもしれないこの論文を読むことをお勧めします (17 ページの表は、非常に強力な型システムの概念の優れたリストとして役立ちます)。
Scala や Haskell のコンパイラが型を推論するために使用するアプローチは、必ずしも型システムの力とは関係ありませんが、人々がコードを書く方法にはある程度の影響があります。強力な型推論アルゴリズムを使用すると、より抽象的なコードを作成する価値があります (すべての場合にそれが良いことであるかどうかは、自分で判断できます)。
結局のところ、Scala と Haskell の型システムは、問題を解決するための最良のツールをユーザーに提供したいという願望によって推進されていますが、その目標に向けて異なる道を歩んできました。
考慮すべきもう 1 つの興味深い点は、Scala が従来の OO スタイルを直接サポートしていることです。つまり、サブタイプの関係があります (たとえば、List は Seq のサブクラスです)。そして、これは型推論をよりトリッキーにします。これに加えて、Scala ではトレイトを混在させることができます。これは、特定の型が複数のスーパータイプの関係を持つことができることを意味します (さらにトリッキーになります)。
Scalaにはランクnタイプはありませんが、場合によってはこの制限を回避できる可能性があります。
私は Haskell の経験がほとんどありませんが、Scala の型システムが Haskell と異なることに最も明白に気付くのは、型推論です。
Scala では、グローバルな型推論はありません。関数の引数の型を明示的に伝える必要があります。
たとえば、Scala では次のように記述する必要があります。
def add (x: Int, y: Int) = x + y
それ以外の
add x y = x + y
これは、「+」メソッドを持つすべての種類のタイプで機能する add 関数の汎用バージョンが必要な場合に問題を引き起こす可能性があります。これには回避策がありますが、より冗長になります。
しかし、実際に使用してみると、Scala の型システムは日常的に使用するのに十分強力であることがわかりました。また、ジェネリックに対してこれらの回避策を使用することはほとんどありません。これは、私が Java の世界から来たからかもしれません。
また、引数の型を明示的に宣言することの制限は必ずしも悪いことではありません。とにかくそれを文書化する必要があります。
さて、それらはチューリング還元可能ですか?
Oleg Kiselyov のページhttp://okmij.org/ftp/を参照してください ... Haskell の型システムでラムダ計算を実装できます。Scala がそれを実行できる場合、ある意味で Haskell の型システムと Scala の型システムは同じ型を計算します。質問は次のとおりです。一方が他方よりもどれほど自然か? どちらが他のものよりもエレガントですか?