如何在Haskell中无限读取和处理用户输入

如何在Haskell中无限读取和处理用户输入,haskell,Haskell,我希望我的命令行Haskell程序的功能如下: 程序等待用户输入 用户键入内容,按“回车” Haskell处理输入,在标准输出上显示结果 Haskell等待下一个用户输入 若并没有更多的输入,用户通过Ctrl+D终止程序 我试过获取内容。但getContents会等待用户在处理所有行之前键入它们。使用和读取输入 这避免了使用interact时出现的惰性i/o问题 (如果不使用isEOF,则按Ctrl+D时将引发异常。) import Control.Monad(除非) 导入System.IO(i

我希望我的命令行Haskell程序的功能如下: 程序等待用户输入

  • 用户键入内容,按“回车”
  • Haskell处理输入,在标准输出上显示结果
  • Haskell等待下一个用户输入
  • 若并没有更多的输入,用户通过Ctrl+D终止程序
  • 我试过获取内容。但getContents会等待用户在处理所有行之前键入它们。

    使用和读取输入

    这避免了使用
    interact
    时出现的惰性i/o问题

    (如果不使用
    isEOF
    ,则按Ctrl+D时将引发异常。)

    import Control.Monad(除非)
    导入System.IO(isEOF)
    processEachLine::(字符串->IO a)->IO()
    processEachLine k=do
    
    完成您可以尝试使用
    交互
    功能。它接受类型为
    String->String
    的函数,并将其转换为读取stdin的操作,将其连续传递给函数,然后写入函数返回stdout的字符串。如果您注意不要过度使用输入字符串,您将获得所请求的行为。

    这里有很多混乱。让我们把事情弄清楚

    我试过获取内容。但getContents会等待用户键入所有行,然后再进行处理

    这里最可能的情况是,您已经编译了程序,但没有注意到输出的默认缓冲是块缓冲。这很容易解决:

    f line = putStrLn ("Hi, " ++ line ++ "!")
    
    main = do
        hSetBuffering stdout LineBuffering -- or use NoBuffering
        putStrLn "Enter some names."
        input <- getContents
        mapM_ f (lines input)
    

    …程序将在每行之后打印更多的输出。您可能还想将
    stdin
    的缓冲设置为
    NoBuffering
    (而不是默认的
    LineBuffering
    ),因为
    show
    的效率足够高,它确实可以在每次击键后产生更多的输出。

    特别是,
    交互(unlines.map processTheInput.lines)
    。非常好!但在我的第一次尝试中,我使用了“互动秀”,但它不起作用。你知道为什么吗?@osager因为
    show
    在其全部输入用尽之前不会返回任何输出<代码>交互
    需要一个递增求值函数。@osager另外,请检查缓冲是否设置为Line@Ptharien'sFlame来自IRC频道的人建议我使用它:hSetBuffering stdin LineBuffering。但是“交互显示”仍然不起作用
    getContents
    返回一个延迟的字符列表。也许消费函数太严格了。如果你想输入一个
    String->String
    类型的函数,你可以很容易地创建一个类似的助手:
    processLinesPure::(String->String)->IO();processLinesPure f=processEachLine(putStrLn.f)
    f line = putStrLn ("Hi, " ++ line ++ "!")
    
    main = do
        hSetBuffering stdout LineBuffering -- or use NoBuffering
        putStrLn "Enter some names."
        input <- getContents
        mapM_ f (lines input)
    
    main = do
        hSetBuffering stdout NoBuffering
        interact show