Haskell中iterate组合IO操作出现累加器反复重置问题求解
现象原因
- 核心原因是Haskell中的IO动作是待执行的副作用指令,而非执行后的结果值,嵌套IO动作每次被调用时都会从头完整执行所有内层逻辑。
- 你的代码中
iterate (printAdd =<<) (pure 0)会生成无限嵌套的IO动作列表,第k个元素对应k-1层嵌套,执行时会完整跑k-1次printAdd,每次都从pure 0开始计算。 sequence会按顺序执行列表中所有IO动作:- 执行第2个元素时运行1次
printAdd,对应第1次输入 - 执行第3个元素时先重新运行1次
printAdd 0(累加器重置为0,对应第2次输入),再运行1次外层printAdd(对应第3次输入) - 执行第4个元素时先重新运行1次
printAdd 0(累加器再次重置,对应第4次输入),再依次运行外层两层printAdd(对应第5、6次输入)
- 执行第2个元素时运行1次
- 重置出现的位置正好是三角数1、3、6、10...,和你观察到的现象完全吻合。
修复方案
你需要的是可传递前序执行结果的无限循环,不需要重复执行之前的IO逻辑,有两种常见实现方式:
递归实现(无额外依赖)
main = loop 0 where loop currentSum = do inputStr <- getLine let newSum = currentSum + read inputStr print newSum loop newSum
函数式风格实现(使用标准库工具)
调用Control.Monad下的iterateM_,它会自动传递上一步的返回值作为下一步的输入,不会重复执行前置逻辑:
import Control.Monad (iterateM_) main = iterateM_ printAdd 0 printAdd x = do l <- getLine let y = x + read l print y pure y
内容的提问来源于stack exchange,提问作者kunberg
相关产品推荐
相关产品推荐

