我希望我的命令行Haskell程序能够像这样运行: 程序等待用户输入,
我试过getContents。但getContents等待用户在处理之前键入所有行。
答案 0 :(得分:8)
这里有很多混乱。让我们试着清理一下。
我试过getContents。但getContents等待用户在处理之前键入所有行。
这里最可能的是你编译了你的程序,并没有注意到输出的默认缓冲是块缓冲。这很容易解决:
f line = putStrLn ("Hi, " ++ line ++ "!")
main = do
hSetBuffering stdout LineBuffering -- or use NoBuffering
putStrLn "Enter some names."
input <- getContents
mapM_ f (lines input)
如果您不打算在每行用户输入后打印整行(包括换行符),则应使用NoBuffering
。
要获得更准确的答案,我们需要查看您尝试过的无效代码。
问:但是在我的第一次尝试中,我使用:“互动节目”,它不起作用。你知道为什么吗? 答:因为show在整个输入用尽之前不会返回任何输出。
这个答案不太正确。真正的答案是show
生成一个没有换行符的字符串! (虽然字符序列['\\','\n']
有时会显示输入多于一行。)因此,对于interact show
,您必须使用NoBuffering
在stdout
。例如,如果您使用此:
main = do
hSetBuffering stdout NoBuffering
interact show
...程序将在每行后打印更多输出。您可能还想将stdin
的缓冲设置为NoBuffering
(而不是默认的LineBuffering
),因为show
足够高效,以至于每次都能产生更多输出击键。
答案 1 :(得分:7)
您可以尝试使用interact
功能。它采用类型String -> String
的函数,并将其转换为读取标准输入的动作,将其连续传递给函数,并将函数返回的字符串写入标准输出。如果您注意不要过度使用输入字符串,您将获得所请求的行为。
答案 2 :(得分:6)
这可以避免使用interact
时出现的懒惰i / o问题。
(如果我们不使用isEOF
,当我们按Ctrl + D时会抛出异常。)
import Control.Monad (unless)
import System.IO (isEOF)
processEachLine :: (String -> IO a) -> IO ()
processEachLine k = do
finished <- isEOF
unless finished $ do
k =<< getLine
processEachLine k
这里我假设k
函数打印所需的输出本身。可以很容易地修改processEachLine
来打印输出,以便k
可以是纯粹的。