how to write each [String] with writeFile into a File in haskell?
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.
精彩评论