yi lu | 4 Sep 16:21 2013
Picon

How to read a file and return a String?

I want to read a text file, and store it in a String. But readFile will get IO String. I search with google and they tell me it is not necessarily to do so. Can you explain to me why is this? Furthermore, How to read a file and store it in a String?

In fact, I want to read a file and split it into [String] with lines function. Here is what I have tried. link I think I could directly operate on [String]. But it is not true for me.
Yi Lu
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Brandon Allbery | 4 Sep 16:32 2013
Picon

Re: How to read a file and return a String?

On Wed, Sep 4, 2013 at 10:21 AM, yi lu <zhiwudazhanjiangshi <at> gmail.com> wrote:
I want to read a text file, and store it in a String. But readFile will get IO String. I search with google and they tell me it is not necessarily to do so. Can you explain to me why is this? Furthermore, How to read a file and store it in a String?

You do not do so directly. An IO action is a promise to produce a value, not an actual value. (readFile contains a String in the same way the "ls" or "dir" command contains a list of files.)

I suggest you take a look at http://learnyouahaskell.com/input-and-output#files-and-streams to see how IO works in Haskell.

tl;dr: use do notation (which lets you pretend to a limited extent that you can see the String in an IO String) or >>= or fmap to attach a callback to the IO "promise".

    readFile >>= (something that operates on a String and produces an IO whatever)

    do s <- readFile
       (something that operates on a String and produces an IO whatever)

Note that in the end it's still in IO. You can't escape it. (There are actually ways to "escape" but they will get you into trouble fairly quickly because they don't work the way you want them to.)

--
brandon s allbery kf8nh                               sine nomine associates
allbery.b <at> gmail.com                                  ballbery <at> sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe
Tom Ellis | 4 Sep 16:36 2013
Picon

Re: How to read a file and return a String?

On Wed, Sep 04, 2013 at 10:21:37PM +0800, yi lu wrote:
> I want to read a text file, and store it in a *String*. But readFile will
> get *IO String*. I search with google and they tell me it is not
> necessarily to do so. Can you explain to me why is this? Furthermore, How
> to read a file and store it in a String?

You need to lift 'lines' into the IO functor, rather than trying to "remove"
the String from IO (which doesn't make sense).  Try

    fmap lines (readFile "filename")

Tom
Richard A. O'Keefe | 5 Sep 06:48 2013
Picon

Re: How to read a file and return a String?

The original poster wants to
 - read a file
 - get the contents as a String
 - break the string into lines
 - do something with the lines
 - and presumably print the result

Easy.  Put the following lines in a file called 'rf.hs':

file_name = "rf.hs"

main =
    readFile file_name >>= \string -> putStr (process (lines string))

process lines = maximum lines ++ "\n"

Then
    m% ghc rf.hs
    m% ./rf
=>  process lines = maximum lines ++ "\n"

Explanation:

   readFile file_name
	is an IO action which when performed will read the named file
	and deliver a string

   cmd1 >>= \x -> cmd2
	is an IO action which when performed will first perform cmd1,
	then bind its result to x, and then perform cmd2.
	>>= is the fundamental operation for chaining actions together.

   lines
	is a plain old String -> [String] function

   process
	is a plain old [String] -> String function, whatever you want

   putStr x
	is an IO action which when performed will write x

The run time environment causes main to be performed.

Gmane