Search code examples
haskellmonadsio-monaddo-notation

How to wrap char literal in IO monad in Haskell?


I know you're supposed to wrap up the operations you want to perform on a result in a monad rather than unwrap things from the monad.

What I can't find are any idiot-friendly examples of how to do that.

For example, I want to do something like this:

myFunction = do
    c <- getChar
    if (c == 'q')
        then putStrLn "take action 1"
        else putStrLn "take action 2"

But you can't compare a char literal to an IO Char directly.

GHCi version is 8.4.4.

Error Message:

[1 of 2] Compiling Lib              ( /Users/jamesstrieter/hask-tink/src/Lib.hs, interpreted )

/Users/jamesstrieter/hask-tink/src/Lib.hs:66:18: error:
    • Couldn't match expected type ‘IO char’ with actual type ‘Char’
    • In the second argument of ‘(==)’, namely ‘'q'’
      In the expression: x == 'q'
      In an equation for ‘what2do’: what2do x = x == 'q'
    • Relevant bindings include
        x :: IO char
          (bound at /Users/jamesstrieter/hask-tink/src/Lib.hs:66:9)
        what2do :: IO char -> Bool
          (bound at /Users/jamesstrieter/hask-tink/src/Lib.hs:66:1)
   |
66 | what2do x = x == 'q'
   |                  ^^^
Failed, no modules loaded.

Solution

  • The code you posted looks perfectly correct and functional.

    do-notation is a way of working with value in monad.

    c <- getChar within the do block binds c to the char inside the IO Char you get with getChar. You can compare c == 'q' just fine here because c is a plain char, not an IO Char.

    To answer you direct question, you can use the return function to put a pure value into any monad, including IO, so return 'q' "wraps" the character literal 'q' into a monad. This isn't what you want in this case, the code you already have is what you are looking for.