此代码无法在GHC 7.0.3中编译:
import System.IO
main = do
z <- readLn
print z
Run Code Online (Sandbox Code Playgroud)
我的目的是从stdin读取一行并将其存储在z中,以便稍后使用它来执行更高级的操作.错误消息如下所示:
test.hs:5:9:
Ambiguous type variable `a0' in the constraints:
(Show a0) arising from a use of `print' at test.hs:5:9-13
(Read a0) arising from a use of `readLn' at test.hs:4:14-19
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of a 'do' expression: print z
In the expression:
do { z <- readLn;
print z;
return () }
In an equation for `main':
main
= do { z <- readLn;
print z;
return () }
Run Code Online (Sandbox Code Playgroud)
显然有一些我尚未理解的基本内容; 请向我解释为什么它不起作用以及如何解决它.
EDIT1:我通过改变固定的编译错误print z来putStrLn z,让GHC明白,我想读的字符串.但是当我运行程序时,我得到一个运行时错误,我无法理解:
$ ./test
hello!
test: user error (Prelude.readIO: no parse)
$
Run Code Online (Sandbox Code Playgroud)
我刚输入"你好!" 然后输入.请注意,我在OS X上运行x86_64 GHC,这被认为是不稳定的.
编辑2:我将readLn更改为getLine,它无缘无故地神奇地工作.我想知道为什么,但我很高兴它有效.
最终代码:
import System.IO
main = do
z <- getLine
print z
Run Code Online (Sandbox Code Playgroud)
Dav*_*ani 27
readLn作为类型:Read a => IO a.它从用户读取一行,然后将字符串解析为类型a.什么是类型a?这是你想要的任何东西(只要它是一个实例Read).例如:
readAInt :: IO Int
readAInt = readLn
readABool :: IO Bool
readABool = readLn
Run Code Online (Sandbox Code Playgroud)
print有类型Show a => a -> IO ().它需要一个类型Show,并将其打印出来.例如,要打印True,您可以使用print True.要打印Int 42,您可以使用print 42.
在您的示例中,您一起使用print和readLn.这不起作用,因为haskell无法确定readLn应该返回什么类型.print可以采用任何可显示的类型,因此它不会限制返回哪种类型.这使得返回类型readLn不明确,因为haskell无法弄清楚类型.这是错误消息所说的内容.
您可能只是存储用户输入的字符串,而不是将其读入您自己的类型.您可以使用具有该类型的getLine执行此操作getLine :: IO String.类似地,您可以使用putStrLn而不是print仅打印字符串.putStrLn有类型String -> IO ().
dav*_*420 17
这就是你改变代码的原因吧?
import System.IO
main = do
z <- readLn
putStrLn z
Run Code Online (Sandbox Code Playgroud)
putStrLn写一个String到stdout,所以z是String.因此将从标准输入readLn读取String.
但是... readLn期望从stdin读取Haskell格式的值.即不是期望你输入类似的东西This is a string,而是用引号来预测它:"This is a string".
要修复,替换readLn为getLine,读取文字文本,而不是Haskell格式的字符串.
import System.IO
main = do
z <- getLine
putStrLn z
Run Code Online (Sandbox Code Playgroud)
cge*_*cge 10
readLn读回您指定的类型,因此不能以这种方式使用:它需要在指定其类型的函数中使用.另一方面,getLine总是返回一个String,所以它可以做你想要的.
值得注意的是,您可能还想使用putStrLn而不是print; print会添加引号.
因此do { z <- getLine; putStrLn z; }在GHCi中应该做你想要的.
| 归档时间: |
|
| 查看次数: |
20209 次 |
| 最近记录: |