You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell中如何简洁实现Either类型短路列表校验函数

结论
  • 该短路列表校验操作属于标准的monadic操作:核心短路能力完全依托Either e类型的Monad实例实现——只要单次校验返回Left错误,就会立刻终止后续所有计算、直接返回错误,完全符合Monad串联带上下文计算的行为特征。
  • 存在远比重写嵌套case更简洁的实现方式,且完全可以通过>>=运算符改写原有递归逻辑。
使用>>=的改写实现

你手写的嵌套模式匹配逻辑,本质就是在Either e的Monad上下文里串联校验步骤,>>=运算符本身就内置了Left分支的短路处理逻辑,不需要手动写case匹配,改写后代码如下:

validateList :: (a -> Either e a) -> [a] -> Either e [a]
validateList _ []     = Right []
validateList validate (x:xs) =
  validate x >>= \y ->
  validateList validate xs >>= \ys ->
  Right (y:ys)

如果偏好可读性更高的语法糖,等价的do notation写法和上述逻辑完全一致(do块最终会被编译为>>=的嵌套调用):

validateList :: (a -> Either e a) -> [a] -> Either e [a]
validateList _ []     = Right []
validateList validate (x:xs) = do
  y  <- validate x
  ys <- validateList validate xs
  pure (y:ys)
最简洁的通用实现

你提到的逻辑点完全正确:此处列表[]并非作为Monad参与计算,而是作为Traversable类型类的实例使用。Haskell标准库中traverse函数的类型签名为Traversable t => (a -> f b) -> t a -> f (t b),当t取[]、f取Either e时,类型和行为完全匹配当前的校验需求:按顺序遍历列表元素执行校验函数,遇到错误立刻短路返回,全部校验通过则返回包装好的结果列表。
因此最终极简实现只需要一行,和手写递归、>>=改写版本的行为完全等价:

validateList :: (a -> Either e a) -> [a] -> Either e [a]
validateList = traverse

补充说明:traverse本身只要求上下文f是Applicative实例,不需要强Monad约束,Either e的Applicative实例同样实现了Left短路逻辑,因此行为完全符合预期。如果列表作为Monad参与计算,会执行非确定性的多结果组合逻辑,反而和当前单错误短路的需求不符。

内容的提问来源于stack exchange,提问作者gust

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 01:09:25