なぜHaskellなのか?
(gtf.io)-
「非実用的」「学術的」「ニッチ」
- 人々が、私のいちばん好きなプログラミング言語がHaskellだと知ったときに示す反応
- 趣味のプロジェクトだけでなく、実際のWebサーバーを構築するのにも使っている
- ConvergeでHaskellで作業するチームを率いている
-
Haskellに対する誤解
- 汎用プログラミング言語で解ける問題は、他の言語でも解ける
- Python、Rust、Typescriptなどに導入されている多くの機能は、Haskellに着想を得たか、Haskellではより堅牢に実装されている
- 「退屈な技術を選べ」という理念の派生形のように見える
- プログラミングは数学ではなく、数学的要素を排除すべきだという誤った考えがある
-
この記事の目的
- Haskellが大半のプログラマーにとって最良の選択である理由を論理的に説明しようとしている
- 堅牢なソフトウェアを生産的に書きたい人にとって、特に有用である
- ソフトウェアを書くうえでの楽しい側面も強調している
-
アンラーニングとリラーニング
- ほとんどのプログラマーは命令型パラダイムに慣れている
- Haskellは純粋関数型言語であり、学習曲線は急である
- Haskell言語自体は、単純な部分集合に限定すれば学びやすい
- 関数型プログラミングは、プログラムを構成する方法についての完全な転換を要求する
- この過程は、プログラマーとして成長する助けになる
- Alan Perlisの言葉の引用:
プログラミングについての考え方に影響を与えない言語は、知る価値がない。
文法の簡単な説明
-
::は型シグネチャを表す(例:myThing :: String) -
関数呼び出しは括弧を使わず、関数名の後ろに引数を空白区切りで並べる(例:
doSomething withThis withThat) -
型シグネチャの小文字は型変数で、任意の型を表す(例:
head :: [a] -> a) -
2種類の矢印
->と=>がある:->は関数の型を説明する(例:add1 :: Int -> Int)=>は型変数に対する制約を説明し、常に先に来る(例:add1 :: Num a => a -> a)
-
コメントは
--で始まる -
returnは通常の関数であり、想像するような意味ではない -
doは命令型のように見せるための糖衣構文である -
ローカル変数に値を割り当てる方法はいくつかある:
let x = <something> in <expression>または
x <- <something> -
ミスを減らす
- 多くの言語では、コードを「正しく」するために多数のテストケースを書く
- Haskellは型システムと純粋関数型プログラミングによって、この負担を大幅に減らす
- Haskellの強力な型システムは、プログラムに対する具体的な保証を提供し、それを厳格に適用する
- 型システムの特徴:
- nullableな型がない
- 失敗しうる計算を表現できる
- パターンマッチと網羅性チェック
- Primitive Obsessionを自然に回避できる
-
null値がないことの利点
null値が存在しないため、値が期待する型に属しているかを常に把握できる- 実行時エラーを防ぎ、エラーの表面積を減らす
-
失敗しうる計算の表現
MaybeとEither型を使って、失敗しうる計算を明示的に表現するMaybeは、結果があるかもしれないし、ないかもしれない計算を表すsafeHead :: [a] -> Maybe aEitherは2種類の値を持ちうる(Left aまたはRight b)validateAddress :: String -> Either AddressParseError ValidAddress
-
パターンマッチと網羅性チェック
- すべての入力ドメインを扱わなければならず、そうでなければコンパイラがエラーを出す
- これは実行時エラーを防ぎ、プログラムの信頼性を高める
-
Primitive Obsessionの回避
newtypeを使って、意味論的により明確な型を簡単に作れる
newtype VenueName = VenueName String newtype EventName = EventName String -
純粋関数型プログラミングの利点
- データは不変であり、状態変化を心配する必要がない
- 副作用は明示的に扱われ、関数は副作用なしに入力のみに依存する
- これにより、プログラムの予測可能性と安定性が高まる
-
副作用の明示的な処理
IOモナドを使って、副作用をコードから分離し制御する- 関数の型シグネチャを通じて、副作用を起こす関数であることが分かる
sendGreetings :: User -> IO Response -
モナドと効果の制御
- 型クラスとモナドを使って、関数が実行できる効果を正確にエンコードする
- これにより、意図しない副作用を防ぎ、コードの安定性を高める
-
生産性を高める要素
- 強力な型システムと純粋関数型という特性により、コード再利用と概念の一般化が容易になる
FunctorやMonoidのような概念を通じて、さまざまなデータ構造に同じパターンを適用できる
fmap (+2) [1, 2, 3] -- [3, 4, 5] fmap (+2) (Just 2) -- Just 4 -
恐れずにできるリファクタリング
- コンパイラの厳格さにより、コード変更時に新しいバグが発生するリスクが少ない
- 型システムがプログラムのドメインを正確に表現できるようにしてくれるため、安心してコードを修正できる
-
プログラム理解の向上
- 宣言的プログラミングによって、問題ドメインを正確に表現できる
- プログラムの意味を理解しやすくなり、信頼性も高められる
- 不要な複雑さを取り除くことで、プログラムを合理的に推論できるようになる
-
代数的データ型と型クラス
- Haskell内でドメイン特化言語を構築できる
- これはプログラムの理解と保守に役立つ
-
サンプルプログラム
- 簡単な会計ツールを書いて、Haskellの概念を実践的に適用する
エピローグ
- Haskellを使うことは楽しく、生産的である
- 強力で表現力の高い型システムと純粋関数型プログラミングの組み合わせが、Haskellを特別なものにしている
- 他の言語もこうした機能を導入しているが、Haskellではそれらの特徴が根本に据えられている
- Haskellを学ぶことは、プログラミングに対する考え方を変えてくれるだろう
GN⁺の意見
-
Haskellの学習価値
- プログラマーとして思考の幅を広げる助けになる
- 関数型プログラミングのパラダイムを理解すれば、他の言語でもより良いコードを書ける
-
関数型プログラミングの台頭
- 並列処理と並行性に強みがあり、現代のコンピューティング環境に適している
- 副作用を制御することで、予測可能なコードを書ける
-
他の言語との比較
- RustやScalaのように関数型プログラミングを支援する言語もあるが、Haskellの純粋性と型システムは際立っている
- 新しい言語を学ぶ際にも、Haskellの概念は役立ちうる
-
実務への適用可能性
- 初期の学習曲線は急だが、投資した時間に見合うだけの生産性向上が得られる
- 複雑なシステムやエラーに敏感なドメインで有用である
-
コミュニティとエコシステム
- Haskellコミュニティは活発で、多様なライブラリやツールが継続的に開発されている
- オープンソースプロジェクトに参加して、実力を高めることができる
3件のコメント
私は実用性を加えたF#から入門しました
ADTとパターンマッチングはいいけど、モナドとかファンクターとかいう話はあまりしないでください
Hacker Newsの意見
Haskellは部分関数ではなく全域関数を書くよう強制する
Haskellを10年間使ってきたが、ツールは大きく改善された
Haskellの型システムは関数が全域的であることを証明しない
Haskellという言語は良いが、エコシステムはまだ道半ば
Haskellや他の関数型言語を仕事で使いたい
Haskellはプログラミングの考え方とコードアーキテクチャに大きな影響を与えた
Haskellは言語レベルで遅延評価を実験している
Haskellの極端な純粋性と不変性が問題
Haskellはビジネスロジックソフトウェア(BLOBS)に非常に適している