如何在Haskell中重置stdin?

时间:2012-02-09 13:28:38

标签: haskell io stdin

我正在尝试在Haskell中编写urlview克隆。程序读取一条消息(通过STDIN管道传输),提取所有URL并要求用户选择其中一个。

阅读完消息后,STDIN显然达到了EOF。在Python中,我像这样重置STDIN

message = sys.stdin.read()
sys.stdin = open('/dev/tty')
selected_index = raw_input('Which URL to open? ')

我如何在Haskell中实现同样的目标?

2 个答案:

答案 0 :(得分:8)

您无法更改Haskell中的stdin句柄。在Python中,sys.stdin变量仅指向到句柄,因此当您用新文件句柄替换它时,旧的stdin 句柄仍然仍然存在,但sys.stdin 变量现在包含文件句柄。

由于System.IO.stdin句柄在Haskell中是不可变的(和其他许多变量一样,或者我应该说是值),你不能在Haskell中做同样的事情。

您可以使用新句柄打开/dev/tty文件,并使用该句柄从终端读取。您可以在stdin上使用任何句柄上的所有相同操作。只需导入System.IO,每次您使用foo ...获取输入时,请使用hFoo handle ...。例如,要从终端读取一行,请使用以下代码:

import System.IO

-- ...
newstdin <- openFile "/dev/tty" ReadMode
-- Instead of normal getLine; just prepend "h" and pass the handle
line <- hGetLine newstdin

请勿忘记通过拨打hClose来关闭新句柄!

答案 1 :(得分:7)

据我所知,无法在Haskell中“重新分配”内置stdin,但您可以打开/dev/tty的新句柄。 Python代码的直接翻译类似于

import System.IO

main = do
    message <- getContents
    tty <- openFile "/dev/tty" ReadMode
    putStr "Which URL to open? "
    url <- hGetLine tty
    ...