概要
関数型プログラミングにおけるエラーハンドリングは、
例外を投げるものではなく、構造として受け取るものである。
そのために存在するのが Maybe
や Either
といったデータ型であり、
それらは単なる「null安全」の手段にとどまらず、設計レベルでの安全性と意図の明確化を担保する抽象機構だ。
本稿では Haskell を例に、Maybe
/ Either
の構造・活用・設計思想を
理論と実装の両面から丁寧に解説していく。
1. Maybe モナドとは?
✅ 定義
data Maybe a = Nothing | Just a
-
Just a
は「値あり」 -
Nothing
は「値なし」 - null や例外とは異なり、型として明示的に扱う
✅ 例:安全な除算
safeDiv :: Int -> Int -> Maybe Int
safeDiv _ 0 = Nothing
safeDiv x y = Just (x `div` y)
safeDiv 10 2 -- => Just 5
safeDiv 10 0 -- => Nothing
- 例外が起きない
- 呼び出し側は
Maybe
に対して安全に処理を分岐できる
2. Either モナドとは?
✅ 定義
data Either e a = Left e | Right a
-
Right a
は「成功」 -
Left e
は「失敗・理由つき」 -
Maybe
が「成功/失敗の有無」だけなのに対し、Either
はエラー内容を持てる
✅ 例:バリデーションの返却型に
validateName :: String -> Either String String
validateName "" = Left "Name cannot be empty"
validateName name = Right name
validateName "" -- => Left "Name cannot be empty"
validateName "Bob" -- => Right "Bob"
- 明示的に失敗を返す設計
- 呼び出し側は
case
や>>=
で処理を分岐・合成できる
3. モナドとしての振る舞い
✅ モナド則により、合成が可能
import Control.Monad (when)
maybeWorkflow :: Maybe Int
maybeWorkflow = do
x <- Just 10
y <- safeDiv x 2
z <- safeDiv y 0
return z -- => Nothing (途中で失敗)
-
do
記法によって失敗した時点で以降の処理がスキップ - 明確な「中断ポイント」設計が可能に
4. 設計的メリット
観点 | Maybe / Either の利点 |
---|---|
明示性 | エラーが「型」として表現される |
安全性 |
null や throw を排除。すべてコンパイル時に検知可能 |
合成性 | 複数処理をつなぐとき、途中で失敗したら自動的に止まる |
テスト容易性 | 関数が副作用を持たず、戻り値をそのまま検証できる |
5. 実務でのパターン
✅ 典型パターン:入力検証チェーン
validateUser :: String -> Either String String
validateUser name = do
validated <- validateName name
if length validated < 3
then Left "Name too short"
else Right validated
-
Either
を使えば バリデーション処理をチェーンしやすく - 途中で止める設計もシンプルに
6. 設計判断フロー
① エラー内容を伝えたい? → YES → Either
② 成功/失敗だけ区別できればいい? → YES → Maybe
③ 呼び出し元に責任を持たせたい? → YES → 明示的に戻り値として返すべき
④ エラーを「意図的に処理可能」にしたい? → YES → Eitherで合成設計にする
よくある誤解と対策
❌ 「Maybe って null と変わらなくない?」
→ ✅ null
は型が崩壊する。Maybe
は型レベルで扱える=安全に処理を組める
❌ 「Either でのエラー処理は冗長」
→ ✅ 明示的な方が安全。“隠された例外”よりも“表に出た失敗”の方が信頼できる
❌ 「例外を使えば良くない?」
→ ✅ 例外は非同期・非決定的。Either
は同期的・予測可能なエラー処理
結語
Maybe
/ Either
は、
単なる「null安全」や「例外代替手段」ではない。
それは関数型設計における**「失敗を設計に取り込む構造的技法」**であり、
安全性・明示性・合成性を同時に担保するための型指向的エラーハンドリングである。
FPにおけるエラー処理とは、
“予期せぬ失敗”を“構造化された制御可能な振る舞い”へと変換する技術である。