Haskell IO - hGetContents:非法操作(句柄关闭)

Jak*_*zuk 8 haskell

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

let main = do x<-getContents; putStrLn x
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

hGetContents: illegal operation (handle is closed)
Run Code Online (Sandbox Code Playgroud)

我应该怎么做这个IO?是否有一些修复,或者我应该查找另一个模拟IO功能?

Osc*_*erd 8

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

看看使用getContents后的在Haskell的用户指南


Pet*_*lák 6

我建议你也调查另一种方法。getContents和类似的操作存在一些固有的问题:

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

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


n. *_* m. 5

这在正常操作中不会重现

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