How to return True or False in a do expression - Haskell

I'm try to return True or False in this expression, but i'm getting this error, can someone tell me what i'm doing wrong? Thanks.

module Main (main) where
import System.IO (stdout, hSetBuffering, BufferMode(NoBuffering))

main::IO()
simOuNao::String -> Bool

main = do hSetBuffering stdout NoBuffering
      putStrLn "Guess Number v1.0"
      putStrLn "======================"

simOuNao frase = do putStrLn frase
                ans <- readLn
                if ans == 'y' || ans =='Y'
                  then return True
                  else return False

Error message:

• Couldn't match expected type ‘Bool’ with actual type ‘IO Bool’
• In a stmt of a 'do' block: putStrLn frase
  In the expression:
    do { putStrLn frase;
         ans <- readLn;
         if ans == 'y' || ans == 'Y' then return True else return False }
  In an equation for ‘simOuNao’:
      simOuNao frase
        = do { putStrLn frase;
               ans <- readLn;
               if ans == 'y' || ans == 'Y' then return True else return False }

Failed, modules loaded: none.

Upvotes: 0

Views: 8520

Answers (3)

Yann Vernier
Yann Vernier

Reputation: 15887

A do expression is a way to write monadic code in sequence, using lines, let and <-. True and False are Bool constructors, and there is no Monad instance for that. There are homomorphic types such as Identity Bool or Maybe ().

Therefore, given the type declaration simOuNao :: String -> Bool, simOuNao cannot be defined as a do expression. Given that you're using putStrLn inside, it has to return something with the IO monad. So you've given conflicting goals. return lifts values into a monadic type. So the simOuNao version you've written requires specifically the IO monad, and the type becomes simOuNao :: String -> IO Bool.

An additional complication is that you've used readLn. I suspect you meant to use getLine and checking for strings starting with 'y', because as it is the user will need to enter 'y' complete with quotes as readLn will expect a character literal.

It is also possible to use monads within a function that has a non-monadic type, including monads like Identity, Maybe and State, typically using some run function to extract the result. This isn't possible with the IO monad in particular, because its state is not deterministic (it represents the outside world, so all IO that is performed must be delegated from main).

Upvotes: 2

chi
chi

Reputation: 116139

If your function does I/O, you have to declare it in the type by returning IO Bool instead.

simOuNao :: String -> IO Bool
simOuNao frase = do putStrLn frase
                    ans <- readLn
                    if ans == 'y' || ans =='Y'
                      then return True
                      else return False

The user of simOuNao will have to use something like

do ...
   b <- simOuNao frase
   ... -- here b is a Bool

and, of course, the type of this do expression will have to be IO someType once again.

Upvotes: 2

Daniel Wagner
Daniel Wagner

Reputation: 152837

Once in IO, always in IO -- there is no escape.

simOuNao :: String -> IO Bool

Upvotes: 5

Related Questions