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

如何通过List Monad实现自定义语言选择块的非确定性分支选择

问题根因

你参考的示例代码整个experiment的do块运行在[](List Monad)中,<-操作会自动遍历列表中的每个元素;但你自己的代码do块运行在IOThrowsError Monad中,g env sb返回的是IOThrowsError [HStatement],所以x <- g env sb取到的是完整的分支列表,不是单个分支,自然无法传递给接收单个HStatement参数的fstIf。

解决方案

方案1:直接处理列表(最简单,适合不需要全分支非确定性推导的场景)

直接对返回的分支列表做筛选、选分支操作,不需要修改现有monad结构:

fstIf :: HStatement -> Bool
fstIf (If (cond, _)) = hval2bool cond -- 可简化原有冗余的if判断

-- 新增工具函数取If分支的执行体
sndIf :: HStatement -> [HStatement]
sndIf (If (_, body)) = body

h :: Env -> HStatement -> IOThrowsError ()
h env sb = do
  allBranches <- g env sb -- 获取所有守卫已经求值完成的If分支
  let validBranches = filter fstIf allBranches -- 筛选守卫为真的合法分支
  case validBranches of
    -- 没有合法分支可以抛出自定义错误
    [] -> throwError $ StrError "no valid guard in selection block"
    -- 取第一个合法分支执行,也可以替换为随机选择逻辑实现真正的非确定任选
    (target:_) -> mapM_ (evalHStatement env) (sndIf target)

方案2:叠加ListT Monad Transformer(复用List Monad的非确定性语法)

如果你需要和示例一样用do语法表达非确定性逻辑,可以在现有monad栈上叠加ListT transformer,获得List Monad的特性:

import Control.Monad.Trans.List (ListT(..), runListT)
import Control.Monad.Trans (lift)
import Control.Monad (guard)

h :: Env -> HStatement -> ListT IOThrowsError ()
h env sb = do
  allBranches <- lift $ g env sb -- 把底层IOThrowsError的操作提升到ListT栈
  branch <- ListT $ return allBranches -- 绑定列表,自动遍历每个分支
  guard $ fstIf branch -- 过滤不合法分支
  lift $ mapM_ (evalHStatement env) (sndIf branch) -- 执行合法分支的body

-- 外层调用函数,取第一个执行成功的结果即可
runSelectionBlock :: Env -> HStatement -> IOThrowsError ()
runSelectionBlock env sel = do
  execResults <- runListT $ h env sel
  case execResults of
    [] -> throwError $ StrError "no valid guard in selection block"
    _ -> return ()

内容的提问来源于stack exchange,提问作者Mr.Bloom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 21:33:02