【Haskell学習|実務向け】MaybeからEitherへの格上げ:型で語るエラーハンドリングの定石

導入

実務で関数型プログラミングを行っていると、検索処理などで「値が存在しない(Nothing)」という状態に遭遇することは避けられません。しかし、後続の処理では「なぜ存在しないのか」という理由が必要になるケースが多々あります。単なる空値を「エラー」という文脈へと格上げすることで、後続処理の型安全性を高め、デバッグ効率を劇的に向上させることができます。本稿では、Maybe型をEither型へ変換する実用的なテクニックを解説します。

基礎知識

関数型プログラミングにおいて、Maybe型は「値がある(Just x)」か「何もない(Nothing)」の2状態を表し、Either型は「成功(Right x)」か「失敗(Left e)」の2状態を表します。
実務上の課題として、Maybeを返り値に持つ関数をパイプラインで繋いでいると、値が欠落した瞬間に処理が止まり、原因が特定しにくくなることがあります。これをEitherに変換することで、失敗の理由を型として保持し、後続のロジックで「どのエラーが発生したか」を正確にハンドリングできるようになります。

実装/解決策

解決策はシンプルです。Maybeの「何もない」という状態に対して、明示的なエラーメッセージを付与してLeftに変換します。Haskell等の言語では、この操作を抽象化したnoteという関数がよく利用されます。
論理的には、Maybeの値をパターンマッチし、NothingであればLeftにエラーを詰め、JustであればRightで包むという手順です。これにより、値の不在を明確な「ドメインエラー」としてワークフローに組み込めます。

サンプルプログラム

以下は、ユーザーIDからデータを検索する処理を想定した実装例です。

/

  • MaybeをEitherに格上げするユーティリティ関数
  • note :: e -> Maybe a -> Either e a

/
const note = (errorMessage) => (maybeValue) => {
// 値がnull/undefinedならエラーメッセージと共にLeftを返す
if (maybeValue === null || maybeValue === undefined) {
return { type: ‘Left’, value: errorMessage };
}
// 値が存在すればRightで包んで成功として扱う
return { type: ‘Right’, value: maybeValue };
};

// シミュレーション: ユーザー検索関数
const findUserById = (id) => (id === 1 ? { name: ‘Alice’ } : null);

// 実行例
const userId = 999;
const userResult = note(‘ユーザーが見つかりませんでした’)(findUserById(userId));

if (userResult.type === ‘Left’) {
console.error(‘エラー発生:’, userResult.value); // エラーハンドリングへ
} else {
console.log(‘成功:’, userResult.value);
}

応用・注意点

現場での運用において最も注意すべきは、エラーメッセージの粒度です。単に「値がない」という文字列を返すだけでは、ログ調査の際に情報不足になりがちです。可能であれば、エラー型を単なる文字列ではなく、列挙型(Enum)や構造化されたオブジェクトにすることで、呼び出し側がエラーの種類に応じて処理を分岐(パターンマッチ)しやすくなります。
また、複数のMaybeを連結する際は、flatMap(あるいはbind)を組み合わせることで、エラーが発生した時点で即座に処理を中断する「ショートサーキット」を実現できます。これにより、ネストの深いif文を排除したクリーンなコードを維持することが可能です。

コメント

タイトルとURLをコピーしました