I am looking at a simple IO program from the Haskell Wikibook. The construction presented on that page works just fine, but I'm trying to understand "how".
The writeChar
function below takes a filepath (as a string) and a character, and it writes the character to the file at the given path. The function uses a bracket to ensure that the file opens and closes properly. Of the three computations run in the bracket, the "computation to run in-between"---as I understand it---is a lambda function that returns the result of hPutChar h c
.
Now, hPutChar
itself has a declaration of hPutChar :: Handle -> Char -> IO ()
. This is where I'm lost. I seem to be passing h
as the handle to hPutChar
. I would expect a handle somehow to reference the file opened as fp
, but instead it appears to be recursively calling the lambda function \h
. I don't see how this lambda function calling itself recursively knows to write c
to the file at fp
.
I would like to understand why the last line of this function shouldn't read (\h -> hPutChar fp c)
. Attempting to run it that way results in "Couldn't match type ‘[Char]’ with ‘Handle’" which I consider sensible given that hPutChar expects a Handle datatype as opposed to a string.
import Control.Exception
writeChar :: FilePath -> Char -> IO ()
writeChar fp c =
bracket
(openFile fp WriteMode)
hClose
(\h -> hPutChar h c)