我正在尝试理解Haskell IO,但stdin的这个特性最终让我感到困惑:
当我尝试使用一些函数,比如getContents,例如:
let main = do x<-getContents; putStrLn x
I get the following error:
hGetContents: illegal operation (handle is closed)
我该如何使用这个函数进行IO操作呢?有没有什么解决方法,或者我应该寻找另一个类似的IO函数呢?
我正在尝试理解Haskell IO,但stdin的这个特性最终让我感到困惑:
当我尝试使用一些函数,比如getContents,例如:
let main = do x<-getContents; putStrLn x
I get the following error:
hGetContents: illegal operation (handle is closed)
我该如何使用这个函数进行IO操作呢?有没有什么解决方法,或者我应该寻找另一个类似的IO函数呢?
getContents == hGetContents stdin
。实际上,hGetContents
标记其句柄(半)关闭,这意味着任何尝试再次从标准输入读取的操作都会失败。
请查看使用 getContents 后在Haskell 用户指南中的说明。
getContents
和类似操作存在一些固有问题:
getContents
是一种惰性 IO
,这意味着(除了其他问题之外):
getContents
返回的字符串时,数据使用惰性 IO
操作读取。这意味着在纯计算内部,我们可能会遇到 IO
效果和错误。一个更安全的替代方案是使用另一个概念,称为迭代器、管道或传送带。这个想法是你将你的组件描述为读取一些输入数据和/或写输出,然后将它们组合在一起。这使你能够编写非常健壮和优雅的代码。
如果你试着在ghci
中使用getContents
,就像你似乎正在做的那样,第二次使用它时就会发生这种情况。第一次调用会将句柄设置为(半)关闭状态,所有后续尝试使用它的操作都将失败。