开发者

how to write each [String] with writeFile into a File in haskell?

开发者 https://www.devze.com 2023-02-28 19:42 出处:网络
how can i write with writeFile a [String] into it? e.g. i have [\"one\", \"two\", \"th开发者_如何学运维ree\"]

how can i write with writeFile a [String] into it?

e.g. i have ["one", "two", "th开发者_如何学运维ree"]

and i want to get into the file:

one two three

how to do this with haskell? i can write a additional function if needed.


I would suggest to use the unwords :: [String] -> String instead of using intersperse. I would like to simply answer with the follwing simple example, using ghci:

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


This isn't to say anything Tarrasch and prnr haven't said, but the difficulty is arising from not separating IO from pure functions: You say

I have ["one", "two", "three"] and I want this into a file: one two three.

You have a list of strings, and want to do something, i.e. you are looking for a function lkndfhu :: [String] -> IO (). True enough, but if you ask:

What is the thing that I want to write to a (new) file?

you will notice that its the same sort of thing as in this case:

What is the thing that I want to write to stdout?

what is the thing I want to append to file file.txt?

Well, it's "one two three" :: String. You want something that maps ["one", "two", "three"] to "one two three", never mind what you are going to do with "one two three"

So really you are looking for a function lkndfhu_pure :: [String] -> String that you can compose with putStrLn or writeFile filename which are of type String -> IO ()

Well the prelude function concat :: [String] -> String, has the right type, but it would yield "onetwothree" and the file or stdout would look thus:

onetwothree

The Prelude function unlines :: [String] -> String has the right type, but would yield `"one\ntwo\nthree" and the file would look thus:

one
two
three

The pre-given Prelude [String] -> String function you want is unwords, as Tarrasch notes; but as pmr notes unwords and unlines are both compositions of concat :: [[a]] -> [a] with intersperse :: a -> [a] -> [a] -- basically:

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

or, equivalently,

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

(These aren't the definitions actually used by the Prelude.) As pmr notes, the abstractness of intersperse means it can be used with IO in complex ways but there is no sign that this is what you need. Note that unwords unlines and intersperse have variants for the fancier String-like types, e.g. ByteString and Text

If you want to think about document preparation that is consistent with using pure functions before passing to IO you might look at the pretty printing library that comes with the Haskell Platform (there are many others). in ghci type :m +Text.PrettyPrint, then type :browse . ghci (and Hugs) implement the Doc type in a special way, so evaluating an expression exhibits the Doc as it will appear to the reader if you render it to a string and write it to a file:

 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)

These examples are of course pretty primitive, check out all the crazy functions with :browse and the examples in the docs


Use intersperse to get the spaces between the words and append every string in the list to the file at path where xs is your list of words:

mapM_ (appendFile path) (intersperse " " xs)

It probably is faster to flatten the list of strings and write it at once:

writeFile path (concat (intersperse " " xs))

Although the first feels more natural to me.

Edit: Please note that the first and second variant still do different things if the file already contains something. writeFile will simply write a new file while appendFile will append to the existing content. It isn't clear which behaviour you actually want.


I'm surprised nobody has mentioned intercalate, which is the same as concat and intersperse.

0

精彩评论

暂无评论...
验证码 换一张
取 消