Haskell多态函数实现:基于Either的EvalResult二元运算
实现EvalResult的多态二元运算函数
嘿,作为Haskell新手能想到抽象这种运算逻辑真的超棒!咱们一步步把这个evalResultOp函数给搞定。
首先先明确你已经定义的类型(方便咱们统一语境):
type Variable = String type Value = Float type EvalError = [Variable] type EvalResult a = Either EvalError a
你的需求很清晰:接收一个二元运算函数,以及两个EvalResult参数,只有当两者都成功(也就是Right包裹的值)时才执行运算;只要有一个是错误(Left包裹的EvalError),就返回对应的错误。
正确的函数类型与实现
首先修正函数的类型签名,最终的类型应该是:
evalResultOp :: (a -> b -> c) -> EvalResult a -> EvalResult b -> EvalResult c
这个签名表示:传入一个从a和b到c的二元函数,两个分别包裹a和b的EvalResult,返回一个包裹c的EvalResult。
接下来用模式匹配实现逻辑,这是Haskell处理这类分支最直观的方式:
evalResultOp f (Right x) (Right y) = Right (f x y) evalResultOp _ (Left err) _ = Left err evalResultOp _ _ (Left err) = Left err
代码解释
- 第一行:当两个输入都是
Right时,取出里面的x和y,用传入的函数f计算结果,再用Right包裹起来返回。 - 第二行:如果第一个输入是
Left(错误),不管第二个输入是什么,直接返回这个错误。 - 第三行:如果第一个输入没问题,但第二个是
Left,就返回第二个的错误。
测试例子
咱们用加法来测试这个函数:
-- 基于evalResultOp实现加法运算 addEval :: EvalResult Value -> EvalResult Value -> EvalResult Value addEval = evalResultOp (+) -- 测试成功场景 test1 :: EvalResult Value test1 = addEval (Right 3.5) (Right 2.1) -- 结果是 Right 5.6 -- 测试第一个参数错误的场景 test2 :: EvalResult Value test2 = addEval (Left ["x"]) (Right 4.0) -- 结果是 Left ["x"] -- 测试第二个参数错误的场景 test3 :: EvalResult Value test3 = addEval (Right 1.0) (Left ["y", "z"]) -- 结果是 Left ["y", "z"]
扩展小技巧
如果你的需求后续需要合并两个错误(比如当两个输入都是错误时,把错误列表合并),可以修改模式匹配的顺序,专门处理双错误的情况:
evalResultOp f (Right x) (Right y) = Right (f x y) evalResultOp _ (Left err1) (Left err2) = Left (err1 ++ err2) evalResultOp _ (Left err) _ = Left err evalResultOp _ _ (Left err) = Left err
这样当两个输入都是错误时,会返回合并后的错误列表,比如evalResultOp (+) (Left ["x"]) (Left ["y"])会得到Left ["x","y"]。
内容的提问来源于stack exchange,提问作者sheldonzy
相关产品推荐
相关产品推荐

