【问题标题】:how to write each [String] with writeFile into a File in haskell?如何用writeFile将每个[String]写入haskell中的文件?
【发布时间】:2011-04-23 12:50:13
【问题描述】:

如何使用 writeFile 将 [String] 写入其中?

例如我有["one", "two", "three"]

我想进入文件:

one two three

如何用 haskell 做到这一点?如果需要,我可以编写一个附加函数。

【问题讨论】:

  • 到目前为止你尝试过什么?你知道mapM吗?你知道如何将单个字符串写入文件吗?

标签: haskell io


【解决方案1】:

我建议使用unwords :: [String] -> String 而不是intersperse。我想简单地回答以下简单的例子,使用ghci

Prelude> let ss = ["one", "two", "three"]
Prelude> writeFile "myfile" $ unwords ss
Prelude> readFile "myfile"
"one two three"

【讨论】:

    【解决方案2】:

    这不是说Tarraschprnr没说什么,但困难在于没有将IO与纯函数分开:你说

    我有["one", "two", "three"],我想把它写成一个文件:one two three

    您有一个字符串列表,并且想要做某事,即您正在寻找一个函数lkndfhu :: [String] -> IO ()。确实如此,但如果你问:

    我要写入(新)文件的内容是什么?

    您会注意到它与本例中的情况相同:

    我想写入标准输出的内容是什么?

    我要附加到文件 file.txt 的内容是什么?

    嗯,它是"one two three" :: String。你想要将["one", "two", "three"] 映射到"one two three" 的东西,别管你要用"one two three" 做什么

    所以你真的在寻找一个函数lkndfhu_pure :: [String] -> String,你可以用putStrLnwriteFile filename组成String -> IO ()类型的函数

    前奏函数concat :: [String] -> String 具有正确的类型,但它会产生"onetwothree" 并且文件或标准输出将如下所示:

    一二三

    Prelude 函数 unlines :: [String] -> String 具有正确的类型,但会产生 `"one\ntwo\nthree" 并且文件看起来像这样:

    一个
    两个

    您想要的预先给定的 Prelude [String] -> String 函数是 unwords,如 Tarrasch 注释;但正如pmr 注释unwordsunlines 都是concat :: [[a]] -> [a]intersperse :: a -> [a] -> [a] 的组合——基本上:

     unwords mystrings = concat (intersperse " " mystrings)
     unlines mystrings = concat (intersperse "\n" mystrings)
    

    或者,等价的,

     unwords  = concat . intersperse " " 
     unlines  = concat . intersperse "\n" 
    

    (这些不是 Prelude 实际使用的定义。)正如 pmr 所指出的,intersperse 的抽象性意味着它可以以复杂的方式与 IO 一起使用,但没有迹象表明这就是你需要。请注意,unwords unlinesintersperse 具有更高级的类似字符串类型的变体,例如ByteStringText

    如果您想在传递给 IO 之前考虑与使用纯函数一致的文档准备,您可以查看 Haskell 平台附带的漂亮打印库(还有很多其他的)。在 ghci 中输入 :m +Text.PrettyPrint,然后输入 :browse 。 ghci(和 Hugs)以特殊方式实现 Doc 类型,因此评估表达式会显示 Doc,因为如果将其呈现为字符串并将其写入文件,则会出现在读者面前:

     PrettyPrint> let lknfdhu_strings = ["one", "two", "three"]
     PrettyPrint> :t lknfdhu_strings
     lknfdhu_strings :: [String]
     PrettyPrint> let lknfdhu = map text lknfdhu_strings
     PrettyPrint> :t lknfdhu
     lknfdhu :: [Doc]
     PrettyPrint> hcat lknfdhu
     onetwothree
     PrettyPrint> hsep lknfdhu
     one two three
     PrettyPrint> vcat lknfdhu
     one
     two
     three
     PrettyPrint> let looksGood = hsep lknfdhu
     PrettyPrint> :t render
     render :: Doc -> String
     PrettyPrint> render looksGood
     "one two three"
     PrettyPrint> render (vcat lknfdhu)
     "one\ntwo\nthree"
     PrettyPrint> let dash =  " - " 
     PrettyPrint> let dashdoc = text dash
     PrettyPrint> dash
     " - "
     PrettyPrint> dashdoc
      - 
     PrettyPrint> hcat ( punctuate dashdoc lknfdhu )
     one - two - three
     PrettyPrint> hcat ( punctuate (text "   ") lknfdhu )
     one   two   three
     PrettyPrint> writeFile "lknfdhu.txt" (render looksGood)
    

    这些示例当然非常原始,请查看 :browse 的所有疯狂函数以及文档中的示例

    【讨论】:

      【解决方案3】:

      使用 intersperse 获取单词之间的空格并将列表中的每个字符串附加到 path 的文件中,其中 xs 是您的单词列表:

      mapM_ (appendFile path) (intersperse " " xs)
      

      将字符串列表展平并立即写入可能会更快:

      writeFile path (concat (intersperse " " xs))
      

      虽然我觉得第一个更自然。

      编辑:请注意,如果文件已经包含某些内容,第一个和第二个变体仍然会做不同的事情。 writeFile 将简单地写入一个新文件,而 appendFile 将附加到现有内容。目前尚不清楚您真正想要哪种行为。

      【讨论】:

        【解决方案4】:

        我很惊讶没有人提到插入,这与 concat 和 intersperse 相同。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-11-21
          • 2023-03-23
          • 1970-01-01
          • 2013-03-01
          • 2011-02-16
          • 1970-01-01
          • 2021-03-07
          相关资源
          最近更新 更多