Hello, several mails spoke about converting an IO String to a String. I have to point out that such a conversion is not what happens when you use monadic I/O. In fact, such a conversion is just not possible in Haskell 98.
Since Haskell is a pure language, evaluating a String expression mustn't cause any side effects. Therefore, if we want to have an operation with side effects, we cannot have an expression of type String. Instead we use an expression of type IO String and we mustn't be able to convert an IO String into a String because, otherwise, we could construct a String expression for the I/O operation using this conversion facility. As the nameless guy pointed out, a value of IO String denotes an I/O operation which has a String as its result. To use this result, you have to combine your I/O operation with a function that has String parameter and returns an I/O operation. The result of this combination is an I/O operation which consists of executing the operation returning the String, applying the function to it and execution the resulting I/O operation. I want to explain this with the readFile/putStrLn example. readFile has the type String -> IO String. Strictly speaking, this does not mean that readFile is an I/O operation which has a String argument and a String result. It means that it is a function which can be applied to String values and has (different) I/O operations for different arguments as its result. Each of these I/O operations is a file reading operation for one specific path name. If we apply readFile to the string "test.dat", we get an operation which reads and returns the content from the respective file. This operation has the type IO String. putStrLn has the type String -> IO (). Applying this function to a String value results in an I/O operation which puts the string to the standard output and a newline after it. Every I/O operation has to have exactly one result value. Since putting a line has no meaningful result, the type () is used as the result type. The type () is a type which has (apart from _|_ which denotes undefindness) the value () as its only value. Now, having readFile "test.dat" and putStrLn, we can combine these two using the monadic bind operator >>=. Specialized for I/O operations, this operator has the type IO a -> (a -> IO b) -> IO b. Specialized for our example it has the type IO String -> (String -> IO ()) -> IO (). So we are able to write readFile "test.dat" >>= putStrLn and get a value of type IO (). This is an I/O operation which first reads the content from "test.dat", applies putStrLn to it which results in an I/O operation outputting the file content, and finally executes this I/O operation so that the content is written to standard output. Since putStrLn is equivalent to \content -> putStrLn content, we can achieve the same effect by writing readFile "test.dat" >>= \content -> putStrLn content. Using the syntactic sugar of the do notation, we get the equivalent expression do content <- readFile "test.dat" putStrLn content which looks quiet like imperative programming but isn't really this. The most important point is the impossibility of an IO a to a conversion. Once you have an I/O computation you have to use the >>= operator to make its result available to other parts of your program. You cannot make it available by conversion. On the top level, every haskell program has a variable called main which is of type IO (). All a Haskell program does, is executing this I/O operation and this way all your I/O actions can finally get executed. Yours, Wolfgang _______________________________________________ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell