関数型プログラミングを理解する目的でHaskellを勉強していますが、他の言語(Groovy、Python、JavaScriptを中心に)で得た洞察を適用することを期待しています。
Haskellを選択したのは、それが非常に純粋に機能的であり、状態への依存が許されないという印象を持っていたからです。
非常に厳格な型システムをナビゲートすることに興味があったため、Haskellを学ぶことを選択しませんでした。
私の質問はこれです:強力な型システムは非常に純粋な関数型言語の必要な副産物ですか、これはHaskellに固有の無関係な設計の選択ですか?
Haskellの型システムを理解することは、関数型プログラミングを理解するためのアンプだと思います。
純粋に関数型のプログラミングについての問題は、あらゆる種類のことを暗黙的に行うことができる副作用がない場合、純粋に関数型のプログラミングはプログラムの構造をより明確にすることです。
Haskellは、カーペットの下に物事を押し込むのを防ぎ、プログラムの構造を明示的に処理するように強制し、これらの構造を記述する言語、つまり型の言語を教えます。型、特にHaskellのような豊富な型を理解することで、あらゆる言語でより優れたプログラマーになります。
Haskellが強く型付けされていなければ、モナドやアプリケーションファンクタなどの概念がプログラミングに適用されることはありません。
最も動的に型付けされた関数型言語は間違いなくSchemeです。とはいえ、Haskellの型システムはその純度の指標です。それは「純度をどのように測定するのか」という問題です。 Haskellの型システムを使用すると、IO
の不純なアクションを簡単に回避できます。そのためには、静的型システムが必要です。
しかし、Haskellの型システムが関数型プログラミングとは何の関係もないとしましょう。型システムがこの教育の取り組みを支援しないと主張するのは、依然として傲慢の高さでしょう。 Haskellの型システムはリッチで複雑であり、C++とOCamlの型システムと比較すると、さらに興味深いものです。
それは障害ですか?いいえ、それは資産だと思います。たとえば、IO
なしでHaskellの怠惰に対処する方法を検討してください。
Clojureは動的に型付けされており、Haskellとほぼ同じように純粋であるため、Haskellの型システムは絶対的な要件というよりは設計上の選択であったという十分な議論があります。どちらにも確かに長所があるので、Haskellの剛性が本当に気に入らない場合はClojureを検討することをお勧めします(ただし、以下を参照)。
私が最初にHaskellを使い始めたとき、私は型システムは煩わしいと考え、型の推論のためにそれだけを許容しました。私はすぐに、コンパイラーが許可していたとしても(たとえばconcatMapの代わりに誤ってmapを使用したとしても)機能しなかったであろうことについてコンパイラーが文句を言うタイプエラーの多くを発見しました。その後、型チェックに合格したプログラムは通常は正しいか、少なくともほぼ正しいことに気づきました。関数タイプを変更し、コンパイラーに他に何を変更する必要があるかを通知させることで、リファクタリングを行う遅延フェーズさえありました。最後に、Haskellの型システムが実際には非常に表現力豊かであることを認識し、型を中心に私のプログラムの設計を開始しました。それがハスケルの聖杯です。
Haskellの型システムは、純粋なコードから効果を分離する機能の鍵です。別の方法で効果を分離できるか、効果を完全に削除できない限り、強力な静的型システムは純粋な関数型プログラミングの要件です。
Haskellは、強力で静的な型システムを持つ言語の非常に良い例です。特にコンピューターサイエンスとプログラミング言語の設計について幅広く丸みを帯びた教育が必要な場合は、Haskellを学習する必要がある言語の1つとして最適です。
型システムは大きな障害であってはなりません。プログラミングを行う人々は、動的言語を使用している場合でも、Haskellの型システムを使用してエンコードできる入力規則に従う傾向があります。 Haskellには、C++やJavaなどの言語と比較して冗長性を軽減する型推論も備わっています。エラーメッセージが表示された場合、コンパイラーは、コンパイル時に動的型を持つ言語が実行時に何を通知するかを通知するだけです。
動的型システムの反対は静的型システムであり、強い型システムではありません。強い型システムは弱い型システムの反対です。
ばかげた間違いをするとすぐにわかります。これは役に立ちます。私はこの最後の用語でラケット(スキーム)で作業しており、パースされていないs-expを渡して、インタープリターの一部の関数にパースされたastを期待したことが何度もありました。中規模のテストスイート。静的型付けがあった場合、それはすぐに私の注意を引いたでしょう。
もちろん、論理エラーは実際には型システムでキャッチすることはできませんが、失敗する方法の数は大幅に減少します。
また、型推論では、必要に応じて型システムを無視できます。それはまだそこにありますが、あなたの側でアクティブな入力を必要としません。関数のタイプを理解することは依然として役に立ちますが、正しいコードは問題なく機能します。
Haskellの純粋性は、その型システムでエンコードされています。 IOモナドは、純粋でないコードが純粋な関数にリークするのを阻止するタイプレベルの構造体です。そのため、純粋性はタイプシステムによって保証されます。
「関数型」言語であることは、(他のものは別として)関数がその言語のファーストクラスのオブジェクトであることを意味します。
「純粋な」言語であるということは、関数が(手続きではなく)数学関数であることを意味します-同じ入力が与えられた場合、それらはalwaysが同じ出力を生成します。
「純粋な関数型言語」は、上記の両方が当てはまる言語です。私は「純粋なly関数型言語」に気づいていません。
強力な型システムは、純粋でありながら実用的な言語を使用する1つの方法cleanです。タイプは、コンパイラーが最適化を理解するのに役立ちます。別の形式では、正確さがさらに保証されます。 (しかし、それが唯一の方法ではありません。clojureは純粋ですが、Haskellほど強力な型システムを持っていません。)
型システムが気になる場合は、Schemeなどのより動的な言語を試すか、Haskellの型推論システムを使用することをお勧めします。
はい、型システムは信じられないほどの資産です。モナドがどのように機能するか、または一部のコンビネータが型システムなしでどのように動作するかを説明することさえ非常に難しいでしょう。 HaskellのチュートリアルがREPLで:tを使用して問題の関数のタイプを検討するように最初に要求する数を検討してください。動的に型付けされた言語では、これはまったく利用できません。確かに、型システムのすべての複雑さはまだ残っています。モナドはまだモナドです。しかし、言語は問題の手を洗い、全く助けを提供しないことを決定しました。あなたは一人で、仲間です。私は動的に型付けされた言語をノックしていません。私は彼らを心から愛しています。 Schemeは卓越したパワーツールです。しかし、動的言語でモナドのようなものについて話すとき、手続きのタイプを説明するために記法を発明するがよくあることに気づくでしょう。関数型プログラマーは、何らかの方法でタイプと戦います。 Haskellのタイプチェッカーは、その方法を学ぶための優れたツールを提供します。