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

Man*_*dor 0 io monads haskell

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

main :: IO ()
main = run theWorld presentationIO

run dom showDom = do
       event <- readCommand
       dom' <- updateDomain dom event 
       showDom dom'
       run dom' showDom
Run Code Online (Sandbox Code Playgroud)

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

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 
   |                ^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

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

提前致谢!

Fyo*_*kin 9

该函数updateDomain,如第 66 行所定义,返回World

但是第96 行的“左箭头”需要箭头右侧的 monadic 值,在当前 monad 中,在您的情况下是IO.

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

然而,正确的解决方案不是让updateDomainreturn IO World,而是放弃左箭头。相反,使用let绑定dom'

run dom showDom = do
  event <- readCommand
  let dom' = updateDomain dom event 
  showDom dom'
  run dom' showDom
Run Code Online (Sandbox Code Playgroud)

  • 或者`dom' &lt;- updateDomain dom &lt;$&gt; readCommand`。 (2认同)