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

不使用Transformer Monad,在Haskell中实现State Monad错误返回

不用Monad Transformer实现State状态校验返回错误

你原来的代码存在类型不匹配问题:State monad的do块中不能直接返回Left,因为Log类型是State [String] (),其上下文的返回值类型是(),和Either类型冲突。而且把State包在Either里的设计逻辑有误——我们需要的是在State执行过程中根据状态判断并返回错误,而非要么返回错误要么返回一个State操作。

不用ExceptT或其他Transformer的解决方案很直接:让State的计算结果类型包含Either,把错误信息作为State执行后的输出部分。

修正后的代码如下:

import Control.Monad.State

stateCheckDuplicate :: String -> State [String] (Either String ())
stateCheckDuplicate elem = do
  currentLog <- get
  if elem `elem` currentLog
    then return $ Left "Duplicate elements"
    else do
      put (elem : currentLog)
      return $ Right ()

代码说明

  • 函数类型改为String -> State [String] (Either String ()):表示传入一个字符串,执行一个State操作,最终返回Either——成功时返回Right ()并更新状态,失败时返回Left错误信息且状态不变。
  • 用elem检查元素是否存在:你原来的lookup适用于键值对列表(比如[(k,v)]),这里状态是[String]直接存元素,用elem更准确。
  • 执行时用runState获取结果和最终状态:
-- 首次添加元素,成功
runState (stateCheckDuplicate "apple") []  -- 结果:(Right (), ["apple"])
-- 添加重复元素,返回错误
runState (stateCheckDuplicate "apple") ["apple"]  -- 结果:(Left "Duplicate elements", ["apple"])

这种方式完全不需要任何Monad Transformer,只是利用State monad的结果类型承载错误信息,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 01:38:15