如何将all/any应用于返回Either类型的函数?
实现Either上下文中的all/any函数
问题背景
我们有一个返回Either String Bool的函数,用于判断两个有理数的关系,遇到除数为0时返回错误信息:
testPre :: Rational -> Rational -> Either String Bool testPre a b | b == 0 = Left "Shouldn't be 0" | a > b = Right True | a <= b = Right False
需要实现适配Either String Bool类型的all和any函数,使其能在Either上下文处理列表,满足以下预期行为:
-- all函数预期结果 allEither (testPre 3) [1,2] => Right True allEither (testPre 3) [1,2,3] => Right False -- any函数预期结果 anyEither (testPre 3) [1,5] => Right True anyEither (testPre 3) [5,6] => Right False -- 遇到错误时立即返回 anyEither (testPre 3) [1,0,3] => Left "Shouldn't be 0"
实现方案
核心逻辑是遍历列表时优先处理错误:一旦遇到Left就终止遍历并返回该错误;若为Right Bool则按照all/any的语义累积结果。
代码实现
import Data.Ratio (Rational) testPre :: Rational -> Rational -> Either String Bool testPre a b | b == 0 = Left "Shouldn't be 0" | a > b = Right True | a <= b = Right False -- 适配Either的all函数:所有元素满足条件则返回Right True,否则Right False,遇错返回Left allEither :: (a -> Either e Bool) -> [a] -> Either e Bool allEither _ [] = Right True allEither f (x:xs) = do current <- f x if current then allEither f xs else Right False -- 适配Either的any函数:任一元素满足条件则返回Right True,否则Right False,遇错返回Left anyEither :: (a -> Either e Bool) -> [a] -> Either e Bool anyEither _ [] = Right False anyEither f (x:xs) = do current <- f x if current then Right True else anyEither f xs
验证结果
调用示例与预期完全一致:
allEither (testPre 3) [1,2] -- 输出 Right True allEither (testPre 3) [1,2,3] -- 输出 Right False anyEither (testPre 3) [1,5] -- 输出 Right True anyEither (testPre 3) [5,6] -- 输出 Right False anyEither (testPre 3) [1,0,3] -- 输出 Left "Shouldn't be 0"
细节说明
- 利用Haskell的
do语法糖简化Either的链式处理:当f x返回Left时,整个do块会直接短路返回该错误,无需额外判断。 - 空列表的返回值遵循标准
all/any的语义:all对空列表返回True,any对空列表返回False,这里对应包装为Right值。
内容的提问来源于stack exchange,提问作者Shawn Zhang
相关产品推荐
相关产品推荐

