
Hello, On Thursday 16 August 2001 9:30 pm, Mark Carroll wrote:
Let me know if I'm bugging you guys too much. It'd be great if I had someone close at hand who knew more about Haskell than I do, but unfortunately I don't. Are there any fora that are especially for people to help novices, or is haskell-cafe the best fit?
I decided I ought to learn more about monads, so I've been trying to do simple IO. However, I'm running into really basic problems that I haven't managed to solve with the three monad tutorials I've read so far!
First, given an IO String, I don't seem to be able to take the head of it to get an IO Char. I'm guessing that the IO monad is quite unlike the simple 'tainting' I first imagined; I reall do seem to have to treat it as an abstract polymorphic type. Worse, I can't work out how to write a IO String -> IO Char version of head; I can't make my (x:xs) match an IO String! Better would be if I could somehow write an IO String -> IO Char wrapper for head.
I'm also confused as to why I can write:
readFile "/tmp/foo" >>= putStr
to print out the contents of a file but, in ghci,
let x = readFile "/tmp/foo" putStr x
...doesn't work.
Yep, won't work. As you suspected, your ideas about what IO means are wrong. IO isn't a simple annotation to indicate an 'impure function', and you can't use a function of type a -> IO b in the same way as you would use a function of type a -> b. (IO b) is an abstract data type. A *value* of type (IO b) stands for an *action* which, when *executed* 'returns' a value of type b. You pass the returned value to subsequent actions using the >>= operator. In your example.. readFile :: String -> IO String I.E. readFile is a *function* (not an action) so.. in x = readFile "/tmp/foo", x is an action of type (IO String). In order actually read the file you still have to execute the action x. Something like this should work (prints file backwards) main :: IO () main = let x = readFile "/tmp/foo" -- x is an action which will read the file in do foofile <- x -- foofile is file contents putStr (reverse foofile) Take a look at the Haskell report to see how 'do expressions' get translated into monadic operators and lambda abstractions. The above is equivalent to.. main = let x = readFile "/tmp/foo" in x >>= (\foofile -> putStr (reverse foofile))
Then again, I'm also confused by the way that Simon Thompson's book says that,
(>>=) :: IO a -> (a -> IO a) -> IO a
which I think might be a misprint for,
(>>=) :: IO a -> (a -> IO b) -> IO b
...?
Yes, I think that's a typo. The second form is correct, though if you look in the prelude you'll see it's definition applies to all monad instances, not just the IO monad. Regards -- Adrian Hey