如何在do表达式中返回True或False-Haskell

时间:2018-06-27 20:03:25

标签: haskell io

我尝试在此表达式中返回True或False,但是我遇到此错误,有人可以告诉我我在做什么错吗?谢谢。

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

错误消息:

• 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 }

失败,已加载模块:无。

3 个答案:

答案 0 :(得分:5)

一旦进入IO,就始终处于IO,就无法逃脱。

simOuNao :: String -> IO Bool

答案 1 :(得分:2)

如果函数执行I / O,则必须通过返回IO Bool来声明其类型。

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

simOuNao的用户将必须使用类似的

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

,当然,此do表达式的类型必须再次为IO someType

答案 2 :(得分:2)

do expression是一种使用行let<-顺序编写单子代码的方法。 TrueFalseBool的构造函数,并且没有Monad实例。有同态类型,例如Identity BoolMaybe ()

因此,给定类型声明simOuNao :: String -> BoolsimOuNao不能定义为do表达式。假设您在内部使用putStrLn,它必须返回带有IO monad的内容。因此,您给出了相互矛盾的目标。 return将值提升为一元类型。因此,您编写的simOuNao版本特别需要IO单子,并且类型变为simOuNao :: String -> IO Bool

另一个麻烦是您使用了readLn。我怀疑您是要使用getLine并检查以'y'开头的字符串,因为那样的话,用户将需要输入'y'并加上引号,因为readLn会期望字符文字。

还可以在具有非monadic类型的函数中使用monad,包括IdentityMaybeState之类的monad,通常使用某些run函数提取结果。尤其对于IO单子来说,这是不可能的,因为它的状态不是确定性的(它代表外部世界,因此必须从main委派所有执行的IO)。