Have I just broken Haskell?

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. We also have the problem of how we are going to use hPutStr to put a string to the file. We can't do hPutStr h "it works" because h doesn't have the right type. I tried getting around it by creating a function let put s h = hPutStr h s fmap (put "it works") h But that doesn't work, it says *** Exception: wow: openFile: resource busy (file is locked) I'm guessing what I've done is create a stream OUT OF the file handle, rather than FOR THE file handle. Urgh! Any ideas what the fix is?

On Tue, Mar 17, 2015 at 2: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.
This is wrong because the type of `h` should be Handle, not IO Handle. `fmap` is not the correct function to use here, you use `fmap` to lift a pure function into some Functor. What you need to do is sequence these two IO actions, like this: name <- getLine h <- openFileWrite name Which is equivalent to this: h <- getLine >>= openFileWrite or this (`=<<` is just a flipped `>>=` operator): h <- openFileWrite =<< getLine -bob

I recently encountered the same Exception. It occurs when you open a file
but don't close it using "hClose".
On Mar 18, 2015 3:46 AM, "Bob Ippolito"
On Tue, Mar 17, 2015 at 2:55 PM, Mark Carter
wrote: 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.
This is wrong because the type of `h` should be Handle, not IO Handle. `fmap` is not the correct function to use here, you use `fmap` to lift a pure function into some Functor. What you need to do is sequence these two IO actions, like this:
name <- getLine h <- openFileWrite name
Which is equivalent to this:
h <- getLine >>= openFileWrite
or this (`=<<` is just a flipped `>>=` operator):
h <- openFileWrite =<< getLine
-bob
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

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ï
participants (4)
-
Anurag Ohri
-
Bob Ippolito
-
Chaddaï Fouché
-
Mark Carter