繁体   English   中英

Haskell IO创建一个字符串列表并显示它

[英]Haskell IO create a list of strings and display it

我正在尝试编写一个程序,允许用户通过一次输入一个字符串来建立字符串列表,并在每个步骤后显示列表。

到目前为止,这是我的代码:

buildList :: [String] -> IO ()
buildList arr = do
    putStr "Enter a line:"
    str <- getLine
    if str == "" then
        return ()
    else do
        let newarr = arr : str
        putStrLn ("List is now: " ++ newarr)
        buildList newarr


listBuilder :: IO ()
listBuilder = do
    buildList []

listBuilder通过传入空列表来启动列表,我正在尝试使用递归,以便代码一直运行,直到用户输入空字符串。

它没有用,欢迎任何想法

这是一个理想的输入:

Enter a line: hello
List is now ["hello"]
Enter a line: world
List is now ["hello","world"]
Enter a line:

错误:

Couldn't match type `Char' with `[String]'
Expected type: [[String]]
  Actual type: String
In the second argument of `(:)', namely `str'
In the expression: arr : str
In an equation for `newarr': newarr = arr : str

编辑:

由于线索和使用show ,这修复了它

buildList :: [String] -> IO ()
buildList arr = do
    putStr "Enter a line:"
    str <- getLine
    if str == "" then
        return ()
    else do
        let newarr = arr++[str]
        putStrLn ("List is now: " ++ show newarr)
        buildList newarr


listBuilder :: IO ()
listBuilder = do
    buildList []

你可以通过这个工作

(a)使用arr++[str]而不是arr:str将新字符串放在列表的末尾,因为:只能像singleThing:list一样使用,
(b)将跑动分为单独的功能,和
(c)将结果传递给return以便您可以在程序的其他地方使用它

buildList arr = do
    putStrLn "Enter a line:"
    str <- getLine
    if str == "" then
        return arr
    else do
        tell (arr++[str])

tell arr = do
        putStrLn ("List is now: " ++ show arr) -- show arr to make it a String
        buildList arr

Enter a line:
Hello
List is now: ["Hello"]
Enter a line:
world
List is now: ["Hello","world"]
Enter a line:

done

您可以使用pipesfoldl库以声明方式解决此问题:

import Control.Foldl (purely, list)
import Pipes
import qualified Pipes.Prelude as P

main = runEffect $ P.stdinLn >-> purely P.scan list >-> P.print

您可以将其读作管道:

  • P.stdinLn是用户输入的行的源

  • P.scan行为类似于Data.List.scanl ,管道而不是列表除外。 purely P.scan list表示要连续输出到目前为止看到的值。

  • P.print这些输出列表打印到控制台

以下是此管道的实例示例:

$ ./example
[]
Test<Enter>
["Test"]
ABC<Enter>
["Test","ABC"]
42<Enter>
["Test","ABC","42"]
<Ctrl-D>
$

您也可以通过将参数更改为purely scan来轻松切换折叠线的其他方法。 例如,如果使用Control.Foldl.vector切换list ,则它将输出行而不是列表的向量。

要了解更多信息,您可以阅读管道foldl库的文档。

问题是: data构造函数只能用于将元素追加到列表的开头。 当您编写let arr=arr:str ,您正在使用它将元素放在列表的末尾。 相反,你可以向后构造你的列表,像这样let arr=str:arr或使用++运算符将它附加到列表的末尾,就像这样let arr=arr++[str]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM