P76 - Either Monad 返回错误原因
Either monad
官方模块:
Problems.P76核心函数:eitherGoldbach
← P75 Maybe Monad | P77 List Monad →
题目描述
重写 P75:成功值放在 Right,解析、范围或奇偶校验失败时在 Left 中返回具体原因。
实现
方法一:do 记法
1import Text.Read (readMaybe)
2
3eitherGoldbach :: String -> Either String (Integer, (Integer, Integer))
4eitherGoldbach text = do
5 n <- case readMaybe text of
6 Nothing -> Left "not a number"
7 Just x -> Right x
8 if n > 2 then Right () else Left "not greater than 2"
9 if even n then Right () else Left "not an even number"
10 pure (n, goldbach n)
Either e 的 Monad 实例遇到第一个 Left e 就停止后续计算,因此返回最先发现的错误。
方法二:显式 case 版
1eitherGoldbach :: String -> Either String (Integer, (Integer, Integer))
2eitherGoldbach text =
3 case readMaybe text of
4 Nothing -> Left "not a number"
5 Just n
6 | n <= 2 -> Left "not greater than 2"
7 | odd n -> Left "not an even number"
8 | otherwise -> Right (n, goldbach n)
不使用 Either Monad,纯 case 匹配。
方法对比
| 方法 | 错误策略 |
|---|---|
| Either monad | 每项校验保留独立错误,首个 Left 自动短路 |
| 显式 case | 解析和 guard 集中在一处分支 |
测试
1>>> eitherGoldbach "28"
2Right (28,(5,23))
3>>> eitherGoldbach "1"
4Left "not greater than 2"
5>>> eitherGoldbach "27"
6Left "not an even number"
7>>> eitherGoldbach "hello"
8Left "not a number"
要点总结
Maybe适合只关心成败的内部组合。Either String更适合需要向调用者解释失败原因的边界接口。