Haskellのコースを受講してみて学んだこと


はじめに

Haskell MOOCのコースを受講して、Haskell言語を使った関数型プログラミングの世界に足を踏み入れることができた。このコースは初心者だけでなく、関数型プログラミングに慣れた人にも設計されており、Haskellの基本的な構文から高階関数や代数的データ型などの高度な機能まで、包括的な基礎を提供してくれる。

コース:Haskell MOOC

このコースは2つの大きな部分に分かれている。細かいながら分かり易い無料のオンラインコース教材が含まれており、例と演習が提供されている。

演習に取り組むには、コマンドラインの使用方法とGitバージョン管理システムの基本的な使い方を知っている必要がある。

全部で16回のチャプターがあり、2つのパートに分かれている。パート1では、Haskellの構文と機能の基本を扱い、副作用のない純粋関数型プログラミングに焦点を当てる。I/O(入出力)とモナドはパート2で紹介される。

モナド(monad):計算を順序だてて扱うためのデザインパターン。操作をチェーンし、副作用を管理しつつ、値をカプセル化し、これらの値に関数を適用する方法を提供する。

全16回のチャプターはおおむね同じボリュームだが、いくつかは他よりも多くの内容を含んでいる。各チャプターセットの最後には、そのチャプターのトピックに関する10~30のプログラミング演習があり、すべての演習を解くことでコースを完了させられる。

演習の例:

------------------------------------------------------------------------------
-- Ex 3: implement the Euclidean Algorithm for finding the greatest
-- common divisor:
--
-- Given two numbers, a and b,
-- * if one is zero, return the other number
-- * if not, subtract the smaller number from the larger one
-- * replace the larger number with this new number
-- * repeat
--
-- For example,
--   myGcd 9 12 ==> 3
-- In this case, the algorithm proceeds like this
--
--   a      b
--
--   9      12
--   9      (12-9)
--   9      3
--   (9-3)  3
--   6      3
--   (6-3)  3
--   3      3
--   (3-3)  3
--   0      3
--
-- Background reading:
-- * https://en.wikipedia.org/wiki/Euclidean_algorithm
 

※自分で出した答えは記事の一番下にある。

Haskell:独自のプログラミングパラダイム

関数型プログラミング

Haskellは本質的に関数型の言語であり、主要な構成要素は関数である。状態を変更する一連の命令を書く命令型言語とは異なり、Haskellは関数の適用に焦点を当てている。このパラダイムシフトは、コードの明快さと理論化の容易さの点で独自の利点をもたらす。

純粋性と副作用のない関数(purity and no side effects)

Haskellの最も魅力的な側面の一つは、その純粋性である。Haskellの関数は副作用を持たない。つまり、実行中に状態を変更したり外部とやり取りしたりしない。この純粋性は、同じ入力が与えられた場合、関数が常に同じ出力を返すことを保証し、Haskellのコードを予測可能にし、デバッグを容易にする。

遅延評価(lazy evaluation)

Haskellは遅延評価を採用しており、式は必要なときにのみ評価される。これにより、無限データ構造の作成が可能になり、不必要な計算を回避することでパフォーマンスの最適化が図れる。

強い型と型推論(strong types with type-inference)

Haskellの型システムは強力かつ表現力豊かである。すべての値と式には型があり、コンパイル時にチェックされることで、ランタイムエラーのクラス全体を排除する。さらに、コンパイラは型を推論できるため、明示的な型注釈の必要性を減らしつつ、型安全性を維持する。

Haskellのユースケース

Haskellの独自の特徴は、多様なアプリケーションに適している:

  • 学術研究と教育: Haskellの数学的性質と純粋性は、コンピュータサイエンスおよび関連分野の教育と研究に最適である。
  • 金融システム: Haskellの純粋関数の予測可能性と信頼性は、金融モデリングおよび定量分析に理想的である。
  • コンパイラとインタプリタ: Haskellの強力な型システムとパターンマッチング機能は、コンパイラやインタプリタの作成に有益である。
  • 並行および並列プログラミング: Haskellの純粋性と不変性は、並行および並列プログラムの理論化を簡素化し、バグの発生を減少させる。
  • Web開発: TypeScript、PHP、Goなどほど主流ではないが、HaskellにはYesodのようなフレームワークがあり、型安全性と関数型パラダイムをWeb開発にもたらす。

HaskellをTypeScriptおよびGoとの比較

TypeScript

TypeScriptはJavaScriptのスーパーセットで、動的なJavaScriptの世界に静的型付けをもたらす。TypeScriptはJavaScriptコードの信頼性と保守性を向上させるが、基本的には命令型およびオブジェクト指向であり、クラスや可変状態に焦点を当てている。

  • 型付け: TypeScriptとHaskellはどちらも静的に型付けされているが、Haskellの型システムはより表現力豊かで、広範な注釈なしにコンパイル時に強制される。
  • パラダイム: TypeScriptは関数型も可能な多パラダイムだが、命令型およびオブジェクト指向プログラミングに傾いている。一方、Haskellは純粋に関数型である。
  • ユースケース: TypeScriptは主にWeb開発に使用され、JavaScriptアプリケーションを強化する。HaskellはWeb開発も可能であるが、高い信頼性と数学的アプリケーションを必要とする分野で際立っている。

Go

GoはGoogleによって開発され、システムプログラミングの簡易性と効率性のために設計された。命令型言語であり、並行性に焦点を当てており、バックエンドサービスやクラウドアプリケーションで人気がある。

  • 並行性: Goはgoroutinesを使った並行プログラミングをサポートしており、ネットワークサービスの強力な候補となる。Haskellも並行性をサポートしているが、ソフトウェアトランザクショナルメモリ(STM)や軽量スレッドを使用する異なるパラダイムを通じてサポートしている。
  • 簡易性 VS 表現力: Goはシンプルさと使いやすさを強調しており、しばしば表現力を犠牲にする。Haskellは一方で、豊かな型システムと高度な機能を提供し、より複雑であるが、より強力で安全なプログラミングを可能にする。
  • パフォーマンス: GoはHaskellと同様に効率的なマシンコードにコンパイルされる。ただし、Haskellの遅延評価は時折パフォーマンスオーバーヘッドを引き起こすことがあるのに対し、Goのパフォーマンスはより予測可能である。

まとめ

Haskell MOOCコースは、Haskellの関数型プログラミングパラダイムについて深い理解を提供し、その純粋性、遅延評価、および強い型付けを強調している。HaskellのアプローチはTypeScriptやGoなどの言語とは大きく異なるが、これらの違いは特に数学的精度と信頼性を必要とする分野でのHaskellの強みを際立たせている。今後もHaskellを学び、探求し続けることで、一般的な言語の現状とは異なる視点を持つ機会が増え、プログラマーとしてのスキルを強化することができると感じている。また、Haskellで使われているベストプラクティスを他の言語にも活用できると感じている。

答え

euclideanAlg :: Integer -> Integer -> Integer
euclideanAlg a b
  | a == 0    = b
  | b == 0    = a
  | a > b     = euclideanAlg (a - b) b
  | otherwise = euclideanAlg a (b - a)

執筆Marko Leinikka

文字数:3339
8分で読めます