我正在尝试从用户那里获取输入并根据输入(从此处修改的代码)进行打印:
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
Run Code Online (Sandbox Code Playgroud)
但是,我遇到很多错误:
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 }
Run Code Online (Sandbox Code Playgroud)
问题在哪里,如何解决?
本质上,您的问题是使IO代码与非IO或“纯”代码混淆。
在中isGreen,您有一个do涉及putStrLn和的块getLine。这意味着函数必须返回某种类型的值IO a。您无法从中获得“纯字符串”,这似乎是您的意图。do块的最后一行必须是单声道值,在这种情况下为IO值-因此您不能在这里简单地输入字符串。
但是,您可以使用return函数从中制作IO String出a String,如注释掉的代码“也不起作用”所示:
if (toUpper (head inpStr) == 'Y') then return "YES" else return "NO"
Run Code Online (Sandbox Code Playgroud)
就工作而言,这很好,并且是必需的isGreen。发生错误是由于中发生了什么main。您不能有print一个IO值IO String-an实际上不是字符串,它基本上是将来字符串的“承诺”,它将仅在运行时基于(在这种情况下)用户输入来实现。
但这毕竟main是一个IO动作,所以这不是问题。只需这样做:
main = do
isItGreen <- isGreen
print isItGreen
Run Code Online (Sandbox Code Playgroud)
或者,完全相同,但更简洁
main = isGreen >>= print
Run Code Online (Sandbox Code Playgroud)
您可能更愿意putStrLn使用print,它在打印字符串时将包含引号。
请注意,如果您为每个顶级值(此处isGreen和main)都包括了一个类型签名,那么您将从编译器中获得有关错误位置的更多有用信息。
isGreen使用IO,因此类型必须是IO String,而不是String。这是一个IO操作,可以产生一个字符串,而不是字符串本身。
isGreen :: IO String
isGreen = do
putStrLn "Is green your favorite color?"
inpStr <- getLine
return $ if (toUpper (head inpStr) == 'Y') then "YES" else "NO"
Run Code Online (Sandbox Code Playgroud)
同样,print期望使用String,而不是IO String,因此您需要使用IOmonad实例。(实际上,你应该使用putStrLn,因为你不需要隐含的show是print将使用。)
main = isGreen >>= putStrLn
Run Code Online (Sandbox Code Playgroud)
在这里,>>=正在创建一个新 IO动作,该IO动作将在左侧(isGreen)执行该动作,并将产生的值传递给右侧(putStrLn)的函数。
| 归档时间: |
|
| 查看次数: |
78 次 |
| 最近记录: |