Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

io

haskell

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

e.g. i have ["one", "two", "three"]

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.

like image 688
lknfdhu Avatar asked Nov 28 '22 22:11

lknfdhu


2 Answers

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"
like image 75
Tarrasch Avatar answered Dec 04 '22 08:12

Tarrasch


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

like image 22
applicative Avatar answered Dec 04 '22 08:12

applicative