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

Haskell 如何上报命令行参数校验错误并返回正确退出码

类型错误根源

类型检查不通过的核心原因是case表达式两个分支返回类型不统一:

  • Left 分支调用的printErrorsThenExit被定义为返回IO ()
  • Right 分支return options返回类型为IO Options
    Haskell要求同个case表达式的所有分支必须返回相同类型的值,因此无法编译。
    实际上exitWith是永远不会正常返回的函数(执行后直接终止进程),其原生类型为ExitCode -> IO a,支持多态返回值,可以适配任意IO类型,不需要将工具函数的返回值固定为IO ()。
修正步骤
  1. 首先调整错误退出工具函数的类型签名,利用exitWith的多态特性:
printErrorsThenExit :: [String] -> ExitCode -> IO a
printErrorsThenExit errs code = do
  -- 建议用unlines拼接错误,每条错误单独占一行,比concat可读性更好
  hPutStr stderr $ unlines errs
  exitWith code

修改后这个函数可以在需要任意IO类型的上下文里使用,因为程序走到exitWith就直接退出,不会产生实际返回值。

  1. 此时原有的case逻辑不需要额外改动就能通过类型检查,两个分支会自动统一为IO Options类型:
opts <- case result of
          Left errors   -> printErrorsThenExit errors illegalArgument  
          Right options -> return options
更简洁的写法

可以直接用Either类型自带的either消除器代替手写case,逻辑完全等价,代码更精简:

opts <- either (`printErrorsThenExit` illegalArgument) pure result
可选优化点

当前实现的evaluateActions收集错误时是把新错误插到错误列表头部,最终错误顺序和参数解析顺序是反向的,如果对错误展示顺序有要求,可以在打印前对错误列表做reverse处理,或者调整折叠时的错误拼接顺序。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 11:39:39