web-dev-qa-db-ja.com

Haskellの型システムが他の言語の型システムよりも「強力」な理由は何ですか?

Scala型システムとHaskellのデメリット? 、私は尋ねなければなりません:何具体的には、Haskellの型システムを他の言語の型システム(C、C++、Java)よりも強力にしているのでしょうか。どうやら、Scalaでさえ、Haskellと同じ能力のいくつかを実行することはできません。型システム。具体的には、Haskellの型システム(Hindley–Milner型推論)が非常に強力な理由は何ですか?例を挙げてください。

37
Curry

具体的には、Haskellの型システムを作るのは何ですか

過去10年間、プロパティ検証のロジックとしての柔軟性と強力さの両方を実現するように設計されてきました。

Haskellの型システムは、比較的柔軟で表現力豊かな静的チェックの分野を奨励するために長年にわたって開発されており、いくつかの研究者グループが、強力な新しいクラスのコンパイル時検証を可能にする型システム技術を特定しています。 Scala'sはその地域では比較的開発が進んでいません。

つまり、Haskell/GHCは、強力であり、型レベルのプログラミングを促進するように設計されたロジックを提供します。関数型プログラミングの世界ではかなりユニークなもの。

Haskellの型システムのエンジニアリング努力がとった方向性のフレーバーを与えるいくつかの論文:

23
Don Stewart

Hindley-Milnerは型システムではなく、型推論アルゴリズムです。 Haskellの型システムは、当時、HMを使用して完全に推測することができましたが、その船は長い間、拡張機能を備えた現代のHaskellに向けて航海してきました。 (MLは完全に推測できます)。

間違いなく、すべてのタイプを主にまたは完全に推測する能力は、表現力の点で力を生み出します。

しかし、それは私が質問が本当にしていると思うものではありません。

リンクされていない論文は、他の側面を指摘しています-Haskellの型システムの拡張によりチューリング完全になります(そして現代の型族はそのチューリング完全言語を価値レベルのプログラミングに非常に似たものにします)。このトピックに関するもう1つの素晴らしい論文は、McBrideの Faking It:Simulating Dependent Types in Haskell です。

Scalaに関する他のスレッドの論文:「オブジェクトおよび暗黙としての型クラス」では、もう少し明確にしていますが、実際にこれのほとんどをScalaでも実行できる理由について説明しています。I感じる傾向がありますが、これは実際のScalaの経験からよりも直感的であり、そのよりアドホックで明示的なアプローチ(C++の議論で「名目」と呼ばれるもの)は最終的に少し厄介です。

14
sclv

非常に簡単な例を見てみましょう: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の使用規則をチェックしません。
  • sumJustsのC++タイプは、+が必要であり、0からキャストされることを指定していません。物事が機能しないときに表示されるエラーメッセージは、不可解で奇妙です。 Haskellでは、コンパイラは型がNumのインスタンスではなく、非常に単純であると文句を言うだけです。

要するに、Haskellには次のものがあります。

  • ADT
  • 型クラス
  • 非常に使いやすい構文とジェネリックスの優れたサポート(C++では、すべての不可解さのために避けようとします)
11
yairchu

Haskell言語を使用すると、機能をあきらめることなく、より安全なコードを記述できます。最近のほとんどの言語は、機能を安全性と交換しています。Haskell言語は、両方を持つことが可能であることを示すためにあります。

Nullポインター、明示的なキャスト、緩い型付けなしで生きることができ、それでも完全に表現力豊かな言語を使用して、効率的な最終コードを生成できます。

さらに、Haskell型システムは、デフォルトで怠惰で純粋なコーディングアプローチとともに、並列処理や並行処理などの複雑で重要な問題を後押しします。

ちょうど私の2セント。

8
Cristiano Paris

私が他の言語で本当に好きで見逃していることの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

このために独自の数値型を定義することもできます。

6
fuz

表現力とは?私の理解では、型システムがコードに課すことができる制約、つまり、証明できるコードのプロパティです。型システムの表現力が高いほど、型レベルでより多くの情報を埋め込むことができます(これは、コンパイル時に型チェッカーがコードをチェックするために使用できます)。
他の言語にはないHaskellの型システムのいくつかのプロパティがあります。

  1. 純度。
    純度により、Haskellは純粋なコードとIO対応コード)を区別できます
  2. パラムトリシティ。
    Haskellは、パラメトリシティポリモーフィック関数にパラメトリシティを適用するため、いくつかの法則に従う必要があります。 (一部の言語では、ポリモーフィック関数タイプを表現できますが、パラメトリシティを強制しません。たとえば、Scalaは、引数がポリモーフィックであっても、特定のタイプでパターンマッチングを行うことができます)
  3. ADT
  4. 拡張機能
    Haskellの基本型システムはλ2の弱いバージョンであり、それ自体はそれほど印象的ではありません。しかし、これらの拡張機能を使用すると、非常に強力になります(依存型をシングルトンで表現することもできます):
    1. 実存型
    2. ランクnタイプ(フルλ2)
    3. 型族
    4. データ型(型レベルでの「型付き」プログラミングを可能にします)
    5. GADT.。
0
Poscat