Scala 型システムと Haskell の欠点を読んでいますか? 、私は尋ねなければなりません: 具体的には、Haskell の型システムが他の言語 (C、C++、Java) の型システムよりも強力な理由は何ですか。どうやら、Scala でさえ、Haskell の型システムと同じ機能のいくつかを実行することはできません。具体的には、Haskell の型システム (Hindley–Milner 型推論) がこれほど強力な理由は何ですか? 例を挙げていただけますか?
6 に答える
具体的には、Haskell の型システムを構成するものは何ですか
過去 10 年間、プロパティ検証のロジックとしての柔軟性と強力さの両方を実現するように設計されてきました。
Haskell の型システムは、比較的柔軟で表現力豊かな静的チェック規則を奨励するために長年にわたって開発されてきました。研究者のいくつかのグループは、強力な新しいクラスのコンパイル時検証を可能にする型システム技術を特定しています。Scala はその分野では比較的未開発です。
つまり、Haskell/GHC は強力で、型レベルのプログラミングを促進するように設計されたロジックを提供します。関数型プログラミングの世界ではかなりユニークなものです。
Haskell の型システムに関するエンジニアリングの取り組みの方向性を示すいくつかの論文:
Hindley-Milner は型システムではなく、型推論アルゴリズムです。昔の Haskell の型システムは、HM を使用して完全に推論できましたが、その船は拡張機能を備えた最新の Haskell に向けて長い間航海してきました。(ML は引き続き完全に推論できます)。
ほぼ間違いなく、すべての型を主にまたは完全に推論する能力は、表現力の点で強力です。
しかし、それは私が質問の本当の意味であると私が考えるものではありません。
リンクされていない論文は、Haskell の型システムへの拡張によりチューリングが完全になる (そして、最新の型ファミリにより、そのチューリングが完全な言語が値レベル プログラミングに非常によく似たものになる) という別の側面を指摘しています。このトピックに関するもう 1 つの優れた論文は、McBride のFaking It: Simulating Dependent Types in Haskellです。
Scala に関する別のスレッドの論文「Type Classes as Objects and Implicits」では、実際に Scala でもほとんどのことを実行できる理由について説明していますが、もう少し明示的です。私は感じる傾向がありますが、これは実際の Scala の経験から得たものというよりも直感的なものであり、そのアドホックで明示的なアプローチ (C++ の議論で「公称」と呼ばれるもの) は、最終的には少し面倒です。
非常に単純な例を見てみましょう: Haskell のMaybe.
data Maybe a = Nothing | Just a
C++ の場合:
template <T>
struct Maybe {
bool isJust;
T value; // IMPORTANT: must ignore when !isJust
};
Haskell で、これら 2 つの関数シグネチャを考えてみましょう。
sumJusts :: Num a => [Maybe a] -> a
および C++:
template <T> T sumJusts(vector<maybe<T> >);
違い:
- C++ では、間違いを犯す可能性がさらに高くなります。コンパイラは の使用規則をチェックしません
Maybe。 - の C++ 型は、を必要とし、からキャスト
sumJustsすることを指定していません。動作しないときに表示されるエラー メッセージは不可解で奇妙です。Haskell では、コンパイラは型が のインスタンスではないことを訴えるだけで、非常に簡単です..+0Num
要するに、Haskell には次の機能があります。
- ADT
- 型クラス
- 非常に親しみやすい構文とジェネリックの適切なサポート (C++ の人々は、不可解な性質のために避けようとします)
Haskell 言語を使用すると、機能をあきらめることなく、より安全なコードを書くことができます。今日、ほとんどの言語は安全性のために機能を交換しています: Haskell 言語は、両方を持つことが可能であることを示すために存在します。
null ポインター、明示的なキャスト、緩い型付けがなくても、完全に表現力豊かな言語を使用して、効率的な最終コードを生成できます。
さらに、Haskell 型システムは、コーディングに対するデフォルトの遅延と純粋なアプローチとともに、並列処理や並行処理などの複雑ではあるが重要な問題を後押しします。
ちょうど私の2セント。
私が他の言語で本当に好きで見逃していることの 1 つは、typclasses のサポートです。これは、多くの問題 (たとえば、多変量関数を含む) に対するエレガントなソリューションです。
型クラスを使用すると、非常に抽象的な関数を非常に簡単に定義できますが、それでも完全に型安全です。たとえば、このフィボナッチ関数のように:
fibs :: Num a => [a]
fibs@(_:xs) = 0:1:zipWith (+) fibs xs
例えば:
map (`div` 2) fibs -- integral context
(fibs !! 10) + 1.234 -- rational context
map (:+ 1.0) fibs -- Complex context
このために独自の数値型を定義することもできます。