我希望我的命令行Haskell程序能够像这样运行:程序等待用户输入,
我试过getContents.但getContents等待用户在处理之前键入所有行.
这里有很多混乱.让我们试着清理一下.
我试过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)
Run Code Online (Sandbox Code Playgroud)
NoBuffering如果您不打算在每行用户输入后打印整行(包括换行符),则应使用此选项.
要获得更精确的答案,我们需要查看您尝试过的无效代码.
问:但是在我的第一次尝试中,我使用:"互动节目",它不起作用.你知道为什么吗?
答:因为show在整个输入用尽之前不会返回任何输出.
这个答案不太正确.真正的答案是show产生一个没有换行符的字符串!(虽然字符序列['\\','\n'] 确实出现有时如果输入多行长.)所以,interact show你真的必须使用NoBuffering的stdout.例如,如果您使用此:
main = do
hSetBuffering stdout NoBuffering
interact show
Run Code Online (Sandbox Code Playgroud)
...程序将在每行后打印更多输出.您可能还希望将stdin缓冲设置为NoBuffering(而不是默认值LineBuffering),因为show它足够高效,以至于在每次击键后它确实可以产生更多输出.
您可以尝试使用该interact功能.它接受类型函数String -> String并将其转换为读取标准输入的动作,将其连续传递给函数,并将函数返回的字符串写入标准输出.如果您注意不要过度使用输入字符串,您将获得所请求的行为.
这可以避免您使用的懒惰i/o问题interact.
(如果我们不使用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
Run Code Online (Sandbox Code Playgroud)
这里我假设该k函数自己打印所需的输出.可以很容易地修改processEachLine输出以使其k纯净.