处理用户输入无限,我想我的命令行的Haskell程序的功能是这样的: 程序等待用户输入,如何阅读和哈斯克尔
- 用户类型的东西,按“输入”
- 哈斯克尔处理输入,示出了在stdout
- Haskell中等待下一个用户输入
- 结果如果没有更多的输入,用户按Ctrl +终止程序d
我试过getContents。但getContents等待用户在处理它们之前输入所有行。
处理用户输入无限,我想我的命令行的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)
您应该使用NoBuffering
,如果你不上打印用户输入的每一行后一整行(包括换行符)计划。
想要得到更准确的答案,我们需要看看您尝试过的代码无效。
问:但在第一次尝试时,我使用“交互式显示”,它不起作用。你知道为什么吗?
答:因为显示将不会返回任何输出,直到其整个输入已耗尽。
这个答案不太正确。真正的答案是show
产生一个没有换行的字符串! (虽然字符序列['\\','\n']
确实有时显示,如果输入是超过一行长。)因此,对于interact show
,您确实必须在stdout
上使用NoBuffering
。例如,如果你使用这个:
main = do
hSetBuffering stdout NoBuffering
interact show
...程序将在每行之后输出更多的输出。您可能还想将stdin
的缓冲设置为NoBuffering
(而不是默认的LineBuffering
),因为show
具有足够的生产能力,因此每次击键后都能产生更多的输出。
这可以避免使用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
可以是纯粹的。
如果你想要一个'String - > String'类型的函数,你可以很容易地创建一个类似的helper:'processLinesPure ::(String - > String) - > IO(); processLinesPure f = processEachLine(putStrLn。f)' – 2012-04-18 03:00:29
您可以尝试使用interact
函数。它采用String -> String
类型的函数,并将其转换为读取stdin的动作,将其连续传递给该函数,并将该函数返回的字符串写入stdout。如果你注意不要过度消费输入字符串,你会得到你所要求的行为。
'getContents'返回* lazy *字符列表。也许消费功能太严格了。 – 2012-04-17 16:38:01