8

我试图理解haskell IO,但stdin的这个特性最终让我感到困惑:当我尝试使用getContents之类的函数时,例如:

let main = do x<-getContents; putStrLn x

我收到以下错误:

hGetContents: illegal operation (handle is closed)

我应该如何用这个做任何 IO?有什么解决方法,还是我应该寻找另一个类似的 IO 功能?

4

3 回答 3

9

getContents == hGetContents stdin. 实际上hGetContents标志着它的句柄(半)关闭,这意味着任何试图再次从标准输入读取的东西都会失败。

Haskell 用户指南中查看使用 getContents 之后

于 2013-08-10T10:12:45.070 回答
6

我建议您也研究一种替代方法。有一些固有的问题getContents和类似的操作:

  1. 你可以有一个无效的句柄 - 一个已经关闭的句柄。这在大多数语言中很常见,但我们可以做得更好。理想情况下,我们希望确保一旦关闭句柄,就不能进一步使用它。
  2. getContents是一个懒惰IO的,这意味着(除其他问题外):
    • 我们几乎无法控制手柄何时(如果)关闭
    • 当我们处理由返回的字符串时getContents,使用惰性IO操作读取数据。这意味着在纯计算中我们可以获得IO效果和错误。

更安全的替代方法是使用另一个概念,称为迭代器、管道或管道。这个想法是您将组件描述为读取一些输入数据和/或写入输出然后将它们组合在一起的东西。这使您可以编写非常健壮和优雅的代码。

于 2013-08-11T12:24:30.270 回答
5

这在正常操作中不会重现

如果您尝试使用getContentsfrom inside ghci,就像您似乎正在做的那样,那正是您第二次使用它时会发生的事情。第一次调用会将句柄设置为(半)关闭状态,所有后续使用它的尝试都将失败。

于 2013-08-10T11:55:12.783 回答