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

Haskell中如何复用多个同参数函数的相同输入校验逻辑

解决方案

完全可以简化,你可以通过高阶函数抽离公共校验逻辑的方式消除重复代码,也可以结合Either的Monad特性用do notation实现。

方案1:抽离公共校验高阶函数(最简洁)

把索引越界校验逻辑封装成通用的高阶包装函数,后续所有业务函数直接套用该包装器即可:

-- 公共校验包装函数,入参为实际执行业务逻辑的函数
withIndexCheck :: (Int -> [a] -> Either String a) -> Int -> [a] -> Either String a
withIndexCheck f i lst
    -- 注:原示例的判断条件存在边界问题,索引最大有效值为length lst - 1,故用>=替换>
    | i < 0 || i >= length lst = Left "Index Out of Bounds!"
    | otherwise = f i lst

后续定义func0到func9时无需再重复写校验逻辑:

func0 :: Int -> [a] -> Either String a
func0 = withIndexCheck $ \i lst ->
    -- 此处直接编写func0专属业务逻辑即可
    Right $ lst !! i

func1 :: Int -> [a] -> Either String a
func1 = withIndexCheck $ \i lst ->
    -- 此处编写func1专属业务逻辑
    if even i then Right (lst !! i) else Left "Index must be even"

方案2:结合do notation实现

如果你本身的业务逻辑有多个Either分支,也可以把校验逻辑封装为单独的Either动作,在do块中优先执行校验,利用Monad的短路特性自动返回错误:

-- 单独封装校验动作
checkIndex :: Int -> [a] -> Either String ()
checkIndex i lst
    | i < 0 || i >= length lst = Left "Index Out of Bounds!"
    | otherwise = Right ()

func0 :: Int -> [a] -> Either String a
func0 i lst = do
    checkIndex i lst -- 校验失败时会直接短路返回Left,不会执行后续逻辑
    -- 此处编写func0专属业务逻辑
    Right $ lst !! i

两种方案都可以完全消除校验代码的重复,你可以根据自己业务逻辑的复杂度选择合适的写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 09:15:03