我尝试在此表达式中返回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 }
失败,已加载模块:无。
答案 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
和<-
顺序编写单子代码的方法。 True
和False
是Bool
的构造函数,并且没有Monad实例。有同态类型,例如Identity Bool
或Maybe ()
。
因此,给定类型声明simOuNao :: String -> Bool
,simOuNao
不能定义为do
表达式。假设您在内部使用putStrLn
,它必须返回带有IO
monad的内容。因此,您给出了相互矛盾的目标。 return
将值提升为一元类型。因此,您编写的simOuNao
版本特别需要IO
单子,并且类型变为simOuNao :: String -> IO Bool
。
另一个麻烦是您使用了readLn
。我怀疑您是要使用getLine
并检查以'y'
开头的字符串,因为那样的话,用户将需要输入'y'
并加上引号,因为readLn
会期望字符文字。
还可以在具有非monadic类型的函数中使用monad,包括Identity
,Maybe
和State
之类的monad,通常使用某些run
函数提取结果。尤其对于IO
单子来说,这是不可能的,因为它的状态不是确定性的(它代表外部世界,因此必须从main
委派所有执行的IO
)。