如何处理Haskell中递归函数中的side IO操作?

how to deal with side IO operations in recursive functions in Haskell?

我是Haskell的新手。我想知道为什么这段代码:

main :: IO ()
main = run theWorld presentationIO

run dom showDom = do
       event <- readCommand
       dom' <- updateDomain dom event 
       showDom dom'
       run dom' showDom

.. 不起作用以及如何解决它。错误是:

simpleExampleTextGameV.0.2.hs:96:16: error:
    • Couldn't match expected type ‘IO World’ with actual type ‘World’
    • In a stmt of a 'do' block: dom' <- updateDomain dom event
      In the expression:
        do event <- readCommand
           dom' <- updateDomain dom event
           showDom dom'
           run dom' showDom
      In an equation for ‘run’:
          run dom showDom
            = do event <- readCommand
                 dom' <- updateDomain dom event
                 showDom dom'
                 ....
   |
96 |        dom' <- updateDomain dom event 
   |                ^^^^^^^^^^^^^^^^^^^^^^

为了重现它,您可以启动其余代码: https://github.com/agutie58/landOfLispInHaskell/blob/main/simpleExampleTextGameV.0.2.hs

提前致谢!

函数 updateDomain,定义于 line 66,returns World

但是 line 96 上的“左箭头”在当前单子中需要箭头右侧的单子值,在您的情况下是 IO.

所以这意味着 updateDomain 应该 return IO World,而不仅仅是 World,如果你想在左箭头的右侧使用它do块。

然而,正确的解决方案不是制作updateDomain return IO World,而是放下左箭头。相反,使用 let 绑定 dom':

run dom showDom = do
  event <- readCommand
  let dom' = updateDomain dom event 
  showDom dom'
  run dom' showDom