
On Tue, Mar 17, 2015 at 10:55 PM, Mark Carter
Persuant to my previous question, I have made some progress, but there is something odd going on.
Suppose we want to implement the following algorithm, which is a little simpler than the original problem:
The user types the name of a file as input. Haskell then puts the text "it works" to that file. I tried this:
import System.IO let openFileWrite name = openFile name WriteMode h :: IO Handle h <- fmap openFileWrite getLine -- you need to type in a file name
This looks wrong, because h presumably needs to be a fixed Handle. Being an IO Handle seems to imply it is mutable. Haskell doesn't complain, though.
No it doesn't, nothing is "mutable" in Haskell, you can have IORef or STRef whose content can be mutated in the IO or ST monad but the IORef or STRef themselves won't be mutable. IO Handle is not "a mutable Handle", it's an IO action that returns an Handle... And that's exactly the type of h in your code ! That's because this code doesn't open anything, it read a line and thanks to fmap, it applies openFileWrite to this line, giving you an "IO Handle" in h, an action that would give you an Handle if it was executed... but it is not executed, it is just stocked in h. The type of "fmap openFileWrite getLine" is IO (IO Handle), not as you probably wanted IO Handle. As Bob said, if you want an Handle, you shouldn't use fmap but rather (>>=). Or you could do : act :: IO handle <- fmap openFileWrite getLine h :: Handle <- act but that's really not the usual way to do it (on the other hand it's interesting because it shows you that "IO a" are just values, you can manipulate them just like normal values. Basically your code was "correct", it just didn't give you an Handle (that would have been clear as soon as you tried to use h as an Handle) ! -- Jedaï