[英]Match type errors between IO Char and [Char]
I am trying to get input from user and print out depending on input (code modified from here ): 我正在尝试从用户那里获取输入并根据输入(从此处修改的代码)进行打印:
import Data.Char (toUpper)
isGreen = do
putStrLn "Is green your favorite color?"
inpStr <- getLine
if (toUpper (head inpStr) == 'Y') then "YES" else "NO"
-- following also does not work:
-- if (toUpper (head inpStr) == 'Y') then return "YES" else return "NO"
main = do
print isGreen
However, I am getting many errors: 但是,我遇到很多错误:
testing.hs:7:44: error:
• Couldn't match type ‘[]’ with ‘IO’
Expected type: IO Char
Actual type: [Char]
• In the expression: "YES"
In a stmt of a 'do' block:
if (toUpper (head inpStr) == 'Y') then "YES" else "NO"
In the expression:
do { putStrLn "Is green your favorite color?";
inpStr <- getLine;
if (toUpper (head inpStr) == 'Y') then "YES" else "NO" }
testing.hs:7:55: error:
• Couldn't match type ‘[]’ with ‘IO’
Expected type: IO Char
Actual type: [Char]
• In the expression: "NO"
In a stmt of a 'do' block:
if (toUpper (head inpStr) == 'Y') then "YES" else "NO"
In the expression:
do { putStrLn "Is green your favorite color?";
inpStr <- getLine;
if (toUpper (head inpStr) == 'Y') then "YES" else "NO" }
testing.hs:12:5: error:
• No instance for (Show (IO Char)) arising from a use of ‘print’
• In a stmt of a 'do' block: print isGreen
In the expression: do { print isGreen }
In an equation for ‘main’: main = do { print isGreen }
Where is the problem and how can it be solved? 问题在哪里,如何解决?
Your problem is, essentially, confusing IO
code with non-IO, or "pure" code. 本质上,您的问题是将
IO
代码与非IO
代码或“纯”代码混淆。
In isGreen
, you have a do
block involving putStrLn
and getLine
. 在
isGreen
,您有一个包含putStrLn
和getLine
的do
块。 This means the function must return a value of some type IO a
. 这意味着该函数必须返回
IO a
类型的值。 You can't get a "plain string" from it, which seems to be your intention. 您无法从中获得“纯字符串”,这似乎是您的意图。 The final line of the
do
block must be a monadic value, in this case an IO
value - so you can't simply have a string here. do
块的最后一行必须为一元数值,在这种情况下为IO
值-因此,您不能在这里简单地输入字符串。
However, you can use the return
function to make an IO String
out of a String
, as in the commented out code that "also does not work": 但是,您可以使用
return
函数从IO String
创建IO String
String
,如注释掉的代码“也不起作用”所示:
if (toUpper (head inpStr) == 'Y') then return "YES" else return "NO"
This works fine, and is necessary, as far as isGreen
is concerned. 就
isGreen
而言,这很好,并且是必需的。 The error comes because of what happens in main
. 该错误是由于
main
发生了什么而引起的。 You cannot print
an IO
value - an IO String
is not actually a string, it's basically a "promise" of a future string, that will only materialise at runtime based on (in this case) the user's input. 您无法
print
IO
值IO String
实际上不是字符串,它基本上是将来字符串的“承诺”,只会在运行时基于(在这种情况下)用户输入来实现。
But since main
is an IO
action anyway, this isn't a problem. 但是由于
main
仍然是IO
操作,所以这不是问题。 Just do this instead: 只需这样做:
main = do
isItGreen <- isGreen
print isItGreen
or, completely equivalently, but imo more succinctly, 或者,完全相同,但更简洁
main = isGreen >>= print
You might prefer putStrLn
to print
, which when printing a string will include the enclosing quotes. 您可能更喜欢
putStrLn
print
,它在打印字符串时将包含引号。
Note that, if you had included a type signature for each top level value (here isGreen
and main
), you'd have got more useful information from the compiler as to where the errors were. 请注意,如果您为每个顶级值(此处为
isGreen
和main
)都包含类型签名,那么您将从编译器中获取有关错误位置的更多有用信息。
isGreen
uses IO
, so the type needs to be IO String
, not String
. isGreen
使用IO
,因此类型必须是IO String
,而不是String
。 It is an IO action that can produce a string, not a string itself. 这是一个IO操作,可以产生一个字符串,而不是字符串本身。
isGreen :: IO String
isGreen = do
putStrLn "Is green your favorite color?"
inpStr <- getLine
return $ if (toUpper (head inpStr) == 'Y') then "YES" else "NO"
Likewise, print
expects a String
, not an IO String
, so you need to use the IO
monad instance. 同样,
print
需要一个String
,而不是一个IO String
,因此您需要使用IO
monad实例。 (Actually, you should use putStrLn
, since you don't need the implicit show
that print
will use.) (实际上,您应该使用
putStrLn
,因为您不需要print
将使用的隐式show
。)
main = isGreen >>= putStrLn
Here, >>=
is creating a new IO
action which will execute the IO
action on the left ( isGreen
), and pass the value produced to the function on the right ( putStrLn
). 在这里,
>>=
正在创建一个新的 IO
操作,该操作将在左侧( isGreen
)执行IO
操作,并将产生的值传递到右侧的函数( putStrLn
)。
Since isGreen
here is an IO a
, you can not use if … then … else …
as last line. 由于
isGreen
这是一个IO a
,因此if … then … else …
用作最后一行。 You need to return an IO a
. 您需要返回
IO a
。
You can however use pure
here (or return
, although there is nothing inherently wrong with that, it ): 但是,您可以在此处使用
pure
(或return
,尽管它本质上没有错):
import Data.Char(toUpper)
isGreen :: IO String
isGreen = do
putStrLn "Is green your favorite color?"
inpStr <- getLine
pure (if "Y" == take 1 (map toUpper inpStr) then "YES" else "NO")
Here "Y" == take 1 (map toUpper inpStr)
is more safe, since if the user has written an empty line, then head
will error on the empty list. 这里
"Y" == take 1 (map toUpper inpStr)
更安全,因为如果用户写了空行,那么head
将在空列表上出错。
Since isGreen
has type IO String
, then you can not use print isGreen
, you here can use bind (>>=)
: 由于
isGreen
类型为IO String
,因此您不能使用print isGreen
,因此可以在这里使用bind (>>=)
:
main :: IO ()
main = isGreen
>>= print
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.