web-dev-qa-db-ja.com

なぜ依存して入力しないのですか?

「Haskellが徐々に依存型の言語になりつつある」という意見をいくつかのソースが繰り返し見ています。意味は、ますます多くの言語拡張により、Haskellはその一般的な方向にドリフトしているようですが、まだそこにはありません。

基本的に知りたいことが2つあります。最初は、非常に単純に、「依存型言語」であることは実際には何ですかmean? (うまくいけば、それについてあまり技術的ではありません。)

2番目の質問は...欠点は何ですか?つまり、人々は私たちがそのように進んでいることを知っているので、それに何らかの利点がなければなりません。それでも、私たちはまだそこにいないので、人々がずっと行くのを止めるいくつかの欠点があるに違いありません。問題は複雑さの急激な増加であるという印象を受けます。しかし、依存型付けが何であるかを本当に理解していないので、確かにわかりません。

私がdo知っているのは、依存型のプログラミング言語について読み始めるたびに、テキストがまったく理解できないということです...おそらくそれが問題です。 (?)

158

依存型付けは、実際には値と型レベルの統合にすぎないため、型の値をパラメータ化できます(Haskellの型クラスとパラメータポリモーフィズムで既に可能です)。 、DataKindsは非常に近くなります)。

編集:どうやら、この時点から、私は間違っていたようです(@pigworkerのコメントを参照)。残りは、私が食べてきた神話の記録として保存します。 :P


私が聞いたところによると、完全な依存型付けへの移行に関する問題は、Haskellを消去された型を使用して効率的なマシンコードにコンパイルできる型と値のレベル間の位相制限を破ることです。現在のレベルのテクノロジーでは、依存型付き言語mustは、ある時点で(すぐに、または依存型付きバイトコードにコンパイルされた後に)インタープリターを通過しますまたは類似)。

これは必ずしも根本的な制限ではありませんが、この点で有望に見えるが、GHCにまだ入っていない現在の研究については個人的には知りません。他の誰かがもっと知っているなら、私は修正されてうれしいです。

21

ジョンは、依存型に関するもう1つのよくある誤解です:実行時にのみデータが利用できる場合、それらは機能しません。 getLineの例を実行する方法は次のとおりです。

data Some :: (k -> *) -> * where
  Like :: p x -> Some p

fromInt :: Int -> Some Natty
fromInt 0 = Like Zy
fromInt n = case fromInt (n - 1) of
  Like n -> Like (Sy n)

withZeroes :: (forall n. Vec n Int -> IO a) -> IO a
withZeroes k = do
  Like n <- fmap (fromInt . read) getLine
  k (vReplicate n 0)

*Main> withZeroes print
5
VCons 0 (VCons 0 (VCons 0 (VCons 0 (VCons 0 VNil))))

編集:うーん、それは養豚業者の答えへのコメントであるはずでした。私は明らかにSOで失敗します。

20
ulfnorell

pigworkerは、なぜshould依存型に向かうべきかについて優れた議論をしています:(a)彼らは素晴らしいです。 (b)実際にはsimplify Haskellがすでに行っていることの多く。

「どうして?」質問、私が思ういくつかのポイントがあります。最初のポイントは、依存型の背後にある基本的な概念は簡単ですが(型が値に依存することを許可する)、その基本的な概念の影響は微妙で深遠なことです。たとえば、値と型の区別はまだ有効です。しかし、それらの違いを議論することはfar yer Hindley--MilnerまたはSystem Fよりも微妙になります。これはある程度、依存型が根本的に難しいという事実によるものです(たとえば、一次論理決定できません)。しかし、より大きな問題は、実際に何が起こっているのかを把握して説明するための良い語彙が不足していることだと思います。依存型について多くの人が学ぶにつれて、より良い語彙を開発するので、たとえ根底にある問題がまだ難しい場合でも、物事が理解しやすくなります。

2番目のポイントは、Haskellがgrowing依存型に向かっているという事実に関係しています。私たちはその目標に向かって漸進的な進歩を遂げていますが、実際にそこに到達することなく、インクリメンタルパッチの上にインクリメンタルパッチを持つ言語に固執しています。新しいアイデアが普及するにつれて、他の言語でも同じようなことが起こりました。 Javaは(パラメトリック)ポリモーフィズムを使用しませんでした。そして最終的に彼らがそれを追加したとき、それは明らかにいくつかの抽象化リークと不自由な力による漸進的な改善でした。サブタイプとポリモーフィズムの混在は本質的に難しいことが判明しました。しかし、それがJava Genericsが彼らのやり方で働く理由ではありません。 Javaの古いバージョンに対する漸進的な改善であるという制約のために、彼らは彼らがする方法で働きます。 Ditto、OOPが発明され、人々が「客観的な」C(Objective Cと混同しないように)を書き始めたときなど、C++は厳格であるという装いで始まったことを思い出してくださいCのスーパーセット。新しいパラダイムを追加するには、常に言語を新たに定義する必要があります。そうしないと、複雑な混乱が発生します。これすべての私のポイントは、Haskellに真の依存型を追加するには、ある程度の注意と言語の再構築が必要になることです。しかし、この種のオーバーホールにコミットするのは本当に難しいのですが、私たちが行ってきた漸進的な進歩は短期的には安価に思えます。本当に、GHCをハッキングする人はそれほど多くはありませんが、生き続けるためのレガシーコードはかなりあります。これは、DDC、カイエン、イドリスなどのような非常に多くのスピンオフ言語がある理由の一部です。

19
wren romano