Haskell Problem

C.Reinke C.Reinke@ukc.ac.uk
Tue, 10 Oct 2000 19:58:58 +0100


> The basic aim is to read in a file of data, sort it and then display it.
> 
> I have managed to get a sort to function properly but I am having trouble
> with reading in the data from the file. I have managed to use the
> hGetContents and hGetLine methods of the IO library to read the data in but
> when it is read in, it is stored as an IO String type.
> 
> I would like to convert the input from the file into one large string so I
> can process it before sorting it.
 
> After reading the whole file into a variable, how do I then convert that IO
> String to a String?

a) You don't "read the file into a variable". 

   It might sound picky, but it helps to keep the differences to 
   imperative languages clear in the use of language. In imperative
   languages, variables stand for boxes (storage locations), and you
   can put things into those boxes (read file contents into a variable).

   In functional languages, variables just stand for the things
   themselves.

b) There is no need for a conversion.
   The String is already there for your use. Well, almost. 

   IO String does not actually indicate a String in some capsule 
   but rather an IO-script that, when executed, returns a String. 
   So what you need is a program context 

	- in which your script can be executed 
	  (so that it can actually produce the String)

	- to which the String can be returned
	  (so that you can do something with it)

Putting these two together, you have a script a of type IO String

a :: IO String

and a program p that operates on the String

p :: String -> YourTypeHere

In your case, you want to display the results of your computations,
so p will itself be involved in IO:

p :: String -> IO ()

That means that you can use >>= to put a and p together

main :: IO ()
main = a >>= p

When main is executed, a is executed first and returns a String.
This String is passed as a parameter to p, and the result of 
applying p to the String is executed next.

You can also use do-notation to achieve the same thing

main = do { s <- a; p s }

Here, the variable s stands for a String. That String is not
yet known, so we use the variable instead of it. During execution,
occurrences of the variable will be replaced by a concrete string.

Similarly, the variable main stands for an IO-script. The script
is already known but it is convenient to use the variable instead.
Again, the variable will be replaced by the thing it stands for.

Hth,
Claus

PS. Examples for p:

p0 :: String -> IO ()
p0 s = putStr s

p1 :: String -> IO ()
p1 s = putStr (sort s)