P75 - Maybe Monad 校验输入
Maybe monad
官方模块:
Problems.P75核心函数:maybeGoldbach
← P74 不用 do 的 IO | P76 Either Monad →
题目描述
解析字符串并验证它是大于 2 的偶数,然后返回原数及其哥德巴赫分解。任一步失败都返回 Nothing。
实现
方法一:do 记法
1import Control.Monad (guard)
2import Text.Read (readMaybe)
3
4maybeGoldbach :: String -> Maybe (Integer, (Integer, Integer))
5maybeGoldbach text = do
6 n <- readMaybe text
7 guard (n > 2)
8 guard (even n)
9 pure (n, goldbach n)
readMaybe 处理解析失败,guard False 在 Maybe 中产生 Nothing。do 把三种失败路径串成一条直线。
方法二:模式匹配版(不需 Maybe Monad)
1maybeGoldbach :: String -> Maybe (Integer, (Integer, Integer))
2maybeGoldbach text =
3 case readMaybe text of
4 Nothing -> Nothing
5 Just n
6 | n <= 2 || odd n -> Nothing
7 | otherwise -> let (a, b) = goldbach n
8 in Just (n, (a, b))
用 case 显式处理,不依赖 Monad 抽象。
方法对比
| 方法 | 失败传播 |
|---|---|
| Maybe monad | readMaybe 和 guard 自动短路 |
| 模式匹配 | 每种失败分支显式返回 Nothing |
测试
1>>> maybeGoldbach "28"
2Just (28,(5,23))
3>>> maybeGoldbach "27"
4Nothing
5>>> maybeGoldbach "hello"
6Nothing
Maybe 能表达成功或失败,却不能说明失败原因;P76 用 Either 补上错误信息。