使用 IO.readLn 从 Haskell 中的 stdin 读取单行

发布于 2024-12-10 11:15:04 字数 1262 浏览 0 评论 0原文

此代码无法在 GHC 7.0.3 中编译:

import System.IO

main = do
    z <- readLn
    print z

我的目的是从 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 () }

显然有一些基本的东西我还没有理解;请向我解释为什么它不起作用以及如何修复它。

EDIT1:我通过将 print z 更改为 putStrLn z 修复了编译错误,因此 GHC 知道我想读取字符串。但是当我运行该程序时,我收到一个我无法理解的运行时错误:

$ ./test
hello!
test: user error (Prelude.readIO: no parse)
$

我只是输入了“hello!”然后进入。请注意,我在 OS X 上运行 x86_64 GHC,这被认为是不稳定的。

EDIT2:我将 readLn 更改为 getLine,它毫无理由地神奇地工作了。我想知道为什么,但我很高兴它有效。

最终代码:

import System.IO

main = do
    z <- getLine
    print z

This code does not compile in GHC 7.0.3:

import System.IO

main = do
    z <- readLn
    print z

My intention is to read one line from stdin and store it in z, to do more advanced stuff with it later on. Error message looks like:

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 () }

Obviously there is something fundamental I haven't understood yet; please explain to me why it doesn't work and how to fix it.

EDIT1: I fixed the compile error by changing print z to putStrLn z, so GHC understands that I want to read a string. But when I run the program, I get a runtime error which I can't understand:

$ ./test
hello!
test: user error (Prelude.readIO: no parse)
$

I just typed "hello!" and then enter. Note that I'm running x86_64 GHC on OS X, which is considered unstable.

EDIT2: I changed readLn to getLine and it magically works for no reason. I would like to know why, but I'm happy it works.

Final code:

import System.IO

main = do
    z <- getLine
    print z

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

樱桃奶球 2024-12-17 11:15:04

readLn 作为类型:Read a => IO a。它从用户处读取一行,然后将字符串解析为 a 类型。 a 类型是什么?它是您想要的任何内容(只要它是 Read 的实例)。例如:

readAInt :: IO Int
readAInt = readLn

readABool :: IO Bool
readABool = readLn

print 的类型为 Show 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()。

readLn as the type: Read a => IO a. It reads a line from the user, and then parses the string into type a. What is type a? It is whatever you want (as long as it is an instance of Read). For example:

readAInt :: IO Int
readAInt = readLn

readABool :: IO Bool
readABool = readLn

print has the type Show a => a -> IO (). It takes a type that is an instance of Show, and prints it out. For example, to print True, you can use print True. To print the Int 42, you can use print 42.


In your example, you are using print and readLn together. This doesn't work, as haskell can't figure out what type readLn should return. print can take any type that is showable, so it doesn't restrict to one what type would be returned. This makes the return type of readLn ambiguous as haskell can't figure out the type. This is what the error message is saying.


What you probably what it to store just the string being entered by the user, rather than reading it into your own type. You can do this with getLine, which has the type getLine :: IO String. Similarily you can use putStrLn instead of print to just print a String. putStrLn has the type String -> IO ().

家住魔仙堡 2024-12-17 11:15:04

这就是你更改代码的原因,对吗?

import System.IO

main = do
    z <- readLn
    putStrLn z

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

This is what you changed your code to, right?

import System.IO

main = do
    z <- readLn
    putStrLn z

putStrLn writes a String to stdout, so z is a String. Therefore readLn will read a String from stdin.

BUT... readLn expects to read a Haskell-formatted value from stdin. i.e. instead of expecting you to type something like This is a string, it anticipates it in quote marks: "This is a string".

To fix, replace readLn with getLine, which reads in literal text, not a Haskell-formatted string.

import System.IO

main = do
    z <- getLine
    putStrLn z
罗罗贝儿 2024-12-17 11:15:04

readLn 读回您指定的类型,因此不能以这种方式使用:它需要在指定其类型的函数中使用。另一方面,getLine 始终返回一个字符串,因此它可以执行您想要的操作。

值得注意的是,您可能还想使用 putStrLn 而不是 print ; print 会加引号。

因此 do { z <- getLine; putStrLn z; GHCi 中的 } 应该做你想做的事。

readLn reads back a type that you specify, and so can't be used in this way: it needs to be used in a function that specifies its type. getLine, on the other hand, always returns a String, so it does what you want.

It's worth noting that you might want to use putStrLn instead of print as well; print will add quotation marks.

Thus do { z <- getLine; putStrLn z; } in GHCi should do what you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文