
Hello, I am e-mailing you to see if you could offer me a bit of assistance. I have chosen to use Haskell in a minor assignment at my University, Heriot Watt in Edinburgh. 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? I would be very grateful if you could offer me some assistance in this matter. Thanks Graeme Turner

On Tue, Oct 10, 2000 at 07:11:14PM +0100, Graeme Turner wrote:
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?
You do not have to convert from the abstract data type IO String into String.
You can access the string encapsulated in such abstract data type
using monad operations. The type IO String is the type of the computations
that perform input/output and produces a string as their result. You
can pass this result as an argument to a function of type String -> IO a
which may do the desired manipulation on the string and may also perform
some more input/output and should produce a result of type a.
The do expression is used for sequencing computations, possibly binding
their results to variables, which can then be used in subsequent
computations.
For example, suppose you want to write to standard output the number
of characters read from standard input:
module Main where
import Prelude
main :: IO ()
main = do xs <- getContents
putLine (show (length xs))
This program has two computations. The first one, getContents, read
all available characters from standard input and binds the resulting
string to the variable xs. The second one, putLine (show (length xs)),
finds the length of the string, converts the resulting integer to string
and writes it to standard output.
In your case you may write something similar that sort the input,
instead of find its length.
Romildo
--
Prof. José Romildo Malaquias

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)

Hello! On Tue, Oct 10, 2000 at 07:11:14PM +0100, Graeme Turner wrote:
[...]
I am e-mailing you to see if you could offer me a bit of assistance. I have chosen to use Haskell in a minor assignment at my University, Heriot Watt in Edinburgh. The basic aim is to read in a file of data, sort it and then display it.
[...]
How about import List(sort) main = do fileContents <- readFile "inputFile" -- the do notation hides the bind (>>=) operator. -- fileContents :: String (=== [Char]) let l = lines fileContents -- l :: [String] let sortedL = sort l -- sortedL :: [String] let outputData = unlines sortedL -- outputData :: String putStr outputData Regards, Hannah.

What you need to do is write a function that operates on a string that does what you want it to, and then use that to write some top-level I/O code. If you have a function sortFile :: String -> String, you would write something like this for main: main :: IO () main = do string <- getContents "theFile" putStr (sortFile string) You can treat "string" as a variable that has type String, not IO String, which you can use anywhere you want in "main". Keep in mind, though that what is going on here is quite different than an assignment statement or "converting" a IO String to a String. This is not like the single assignment variables introduced in "where" or "let" clauses, as we cannot substitute the value "(getContents "theFile")" for the variable "string" in main. This would lead to a type error, as sortFile takes a String argument, not an IO String. Nor is is it like the assignment statement in imperative programming languages like C++ and Java for several reasons. One can represent "State Transformers" using monads, so what the IO monad is a state transformer that modifies the state of the computer. int a = 0; int dirty_inc(int a) { a++; return i + a; } int main(int argc, char ** argv) { int i = dirty_inc(1); printf("%i %i", i, i); } Unlike monads, if you "substitute" dirty_inc(1) for i in main will result in a legal program, but it isn't really a substitution, because it would modify the behavior of the program. Moreover, while we could write main = do message <- return "Hello!" message <- return "Goodbye!" putStr message and get "Goodbye!" as output, what really is happening is that you are introducing two variables with the same name, and we can statically determine which one we are referring to. Thus if we write main = do message <- return "Hello!" do message <- return "Goodbye! " putStr message putStr message we will get "Goodbye! Hello!", as output, not "Goodbye! Goodbye!". To start to understand what's really going on, do-notation is just syntactic sugar for using the (>>=) operator. Let's rewrite your example to something that is syntactically equivalent: main :: IO () main = getContents "theFile" >>= (\string -> putStr (sortFile string)) Which we could in turn rewrite as: main :: IO () main = getContents "theFile" >>= output_sort output_sort :: String -> IO () output_sort string = putStr (sortFile string) What (>>=) does is that it takes the String returned inside of a IO String value, and gives it to output_sort, which in turn may use that value in any way it sees fit, *as long as output_sort returns another "IO a" value for some type a.* This is why we are not simply converting a IO String to a String, because in order to use the String value in IO String, we must produce a new IO monad. This is summed up in (>>=)'s type, which is (>>=) :: IO a -> (a -> IO b) -> IO b, which can then be generalized to any monad m, so (>>=) :: m a -> (a -> m b) -> m b. best, leon

On Tue, 10 Oct 2000, Graeme Turner wrote:
Hello,
I am e-mailing you to see if you could offer me a bit of assistance. I have chosen to use Haskell in a minor assignment at my University, Heriot Watt in Edinburgh. 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.
Aha, you want to use readFile :: String -> IO String.
After reading the whole file into a variable, how do I then convert that IO String to a String?
You use '<-' in the do notation. readFile "myfile.txt" -- here you have an IO String do contents <- readFile "myfile.txt" return (lines contents) -- here you "convert" the IO String (readFile "myfile.txt") to a String -- (contents). Finally my example returns a list of the lines in the file. I hope this helps. /Lars L
participants (6)
-
C.Reinke
-
Graeme Turner
-
Hannah Schroeter
-
José Romildo Malaquias
-
Lars Lundgren
-
Leon Smith