Mandor
Mandor

Reputation: 595

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

I am a complete newbie in Haskell. I am wondering why this pice of code:

main :: IO ()
main = run theWorld presentationIO

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

.. does not work and how to solve it. The error is :

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 
   |                ^^^^^^^^^^^^^^^^^^^^^^

In order to reproduce it, you could launch the rest of code: https://github.com/agutie58/landOfLispInHaskell/blob/main/simpleExampleTextGameV.0.2.hs

Thanks in advance!

Upvotes: 0

Views: 189

Answers (1)

Fyodor Soikin
Fyodor Soikin

Reputation: 80714

The function updateDomain, as defined on line 66, returns World.

But the "left arrow" on line 96 requires a monadic value on the right of the arrow, in the current monad, which in your case is IO.

So this means that updateDomain should return IO World, not just World, if you want to use it on the right side of the left arrow in a do block.

The right solution, however, is not to make updateDomain return IO World, but rather to drop the left arrow. Instead, use let to bind dom':

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

Upvotes: 8

Related Questions