2025/03/20 08:37 Non-Obvious Haskell Idiom: Guard-Sequence

ロボ子、Haskellの`guard`シーケンスって知ってるか?

はい、博士。条件によって処理を分岐させるためによく使われるイディオムですよね。

そうじゃ、そうじゃ。`guard condition *> action`、`guard condition $> value`、`value <$ guard condition`の3つの形式があるのじゃ。

`guard condition *> action`は、条件が真の場合に副作用のあるアクションを実行するんですね。例えば、ログを出力したりとか。

その通り!そして、`guard condition $> value`は、条件が真の場合に値を返すのじゃ。`ensure`関数みたいなものじゃな。

記事に`guard (age >= 18) $> ticket_for person`という例がありました。18歳以上の場合にチケットを返すんですね。

`guard`は条件が満たされない場合に`Nothing`を、満たされる場合に`Just ()`を返すのがミソじゃ。

`>`演算子は`Nothing`値に対しては何もせず、`Just`値の中身を右側の値で置き換えるんですね。なるほど。

複数の条件がある場合、Haskell版の方がJavaScript版よりも明確に条件と結果の関連性を示すことができるって書いてあるぞ。

`guard (age >= 18 && age <= 24 || age >= 65) $> ticket_discount`のような例ですね。条件が複雑でも読みやすいです。

`value <$ guard condition`の組み合わせは`if`のように読むことができるのじゃ。`ticket_discount <$ guard (age >= 18 && age <= 24 || age >= 65)`は、条件が真なら割引チケットを返すという意味になるぞ。

条件よりも値に重点を置く場合に便利ですね。

`>`演算子の代わりに`*>`演算子を使用すると、右辺を副作用のある処理にすることができるのじゃ。例えば、`guard (age >= 18) *> munch1 isLetter`は、18歳以上の場合に文字を読み込むパーサーを実行するのじゃ。

パーサーと組み合わせると、より複雑な処理も記述できますね。

しかも、`guard`とシーケンス演算子はジェネリックで、`Maybe`だけでなく、何らかの失敗をサポートするあらゆる型で動作するのじゃ!

汎用性が高いんですね。エラーハンドリングにも使えそうです。

そうじゃ、そうじゃ。ところでロボ子、`guard`を使って、もし私が嘘をついたらエラーを出すプログラムを作ってくれないかの?

博士が嘘をつくことなんてありえませんから、その条件は常に`False`になりますね!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。