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

Haskell do表达式展开正确性验证及含forM_操作的展开规则

你的展开是不正确的,存在两处明显问题:

  • 你对do块中let绑定的处理逻辑错误:do块里的let end = length vals -1属于普通变量绑定,不需要包装为lambda调用的形式。你写的(\end -> (newArray (0,end) 0) (length vals - 1))本身存在语法错误,newArray (0,end) 0返回的是ST类型的Monad值,不是可调用函数,不能直接接参数(length vals -1)。
  • forM_的参数没有补全,缺少遍历范围和对应的数组写入逻辑。

正确的完整展开代码如下:

listToSTUArray :: [Int] -> ST s (STUArray s Int Int)
listToSTUArray vals = 
  let end = length vals - 1
  in newArray (0, end) 0 >>= \myArray ->
     forM_ [0 .. end] (\i -> let val = vals !! i in writeArray myArray i val) >>
     return myArray

含结果丢弃操作的do记法通用展开规则

forM_这类返回值为()、仅需执行副作用不需要保留结果的操作,属于do块中无变量绑定的动作行,对应通用展开规则如下:

  1. do块中带变量绑定的行 x <- action,等价于 action >>= \x -> 后续展开代码
  2. do块中无变量绑定的动作行 action(比如forM_、print这类仅执行副作用的操作),等价于 action >> 后续展开代码
  3. do块中的let 绑定不属于Monad操作,直接将绑定放到当前作用域即可,后续代码可直接引用绑定的变量
  4. 嵌套do块按照上述规则递归展开即可

举个简单示例:

-- 原do记法
do
  x <- readInt
  print x
  let doubleX = x * 2
  print doubleX
  return doubleX

-- 展开后代码
readInt >>= \x ->
print x >>
let doubleX = x * 2 in
print doubleX >>
return doubleX

内容的提问来源于stack exchange,提问作者A. G

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 18:09:02