【问题标题】:How do I read all of standard input in Idris2?我如何读取 Idris2 中的所有标准输入?
【发布时间】:2022-12-03 10:35:14
【问题描述】:

我想弄清楚如何做一些非常简单的事情:阅读全部将标准输入转换为字符串(或者字符串列表也可以)。

PreludegetLine : HasIO io => io String,它可以给我一条线,但它并没有给我一种知道我已经读完的方法。如果没有更多的输入,它只会给我一个空字符串,这意味着如果输入包含空行,除了输入的末尾我无法分辨。

考虑以下程序:

module Example

main : IO ()
module Solve

main : IO ()
main = do
  putStrLn ("'" ++ !getLine ++ "'")
  putStrLn ("'" ++ !getLine ++ "'")
  putStrLn ("'" ++ !getLine ++ "'")
  putStrLn ("'" ++ !getLine ++ "'")
  putStrLn ("'" ++ !getLine ++ "'")
  putStrLn ("'" ++ !getLine ++ "'")

该程序将打印六行,每行用单引号括起来,从标准输入中获取内容。如果我将它编译为 ./example 并使用三行输入运行,中间有一个空行,输出如下:

$ ./example <<EOF
foo

bar
EOF
'foo'
''
'bar'
''
''
''

请注意,它会在标准输入流耗尽后继续打印出行。这意味着如果我把它放在某个递归函数中以获得所有输入,我就没有合理的停止条件。

在构建时不知道会有多少行输入的情况下,读取 Idris2 中所有标准输入的惯用方法是什么?

【问题讨论】:

    标签: idris idris2


    【解决方案1】:

    要读取 Idris2 中的所有标准输入,您可以使用 Prelude 模块中的 getContents 函数。此函数返回一个惰性列表字符串,其中列表的每个元素都是一行标准输入。然后,您可以使用 foldl 函数处理每一行输入,并使用 null 检查来确定何时到达输入末尾。

    这是一个示例,说明如何使用 getContents 和 foldl 读取所有标准输入并将每一行打印到标准输出:

    module Example
    
    main : IO ()
    main = do
      input <- getContents
      foldl (_ line -> putStrLn line) () input
    

    该程序会将标准输入的每一行打印到标准输出,直到到达输入的末尾。 null 函数可用于检查输入列表是否为空,在这种情况下已到达输入末尾。

    或者,您可以使用 while 循环来读取和处理每一行标准输入,直到到达输入的末尾:

    模块示例

    main : IO ()
    main = do
      line <- getLine
      while (not $ null line)
        (putStrLn line)
        (line <- getLine; continue)
    

    在此示例中,只要行变量不为空,while 循环就会继续,并在到达输入末尾时终止。

    【讨论】:

      最近更新 更多