I have the following code for loading contents of the file and parse it with aeson into an object:
loadFromFile filename = do
fileHandle <- openFile ( dataDir "/" filename ) ReadMode
contents <- B.hGetContents fileHandle
let result = fromMaybe initial $! JSON.decode contents in do
hClose fileHandle
return $! result
The problem with this code is that it causes following errors:
filename.json: hGetBufSome: illegal operation (handle is closed)
filename.json: hGetBufSome: illegal operation (handle is closed)
I do not quite understand why it thinks file handle is closed. I am reading it before closing the handle after all. Or is lazy evaluation affecting the order of execution? I tried adding corresponding $!
operators to make it evaluate sooner, but it does not help. If I remove hClose fileHandle
line, then I start getting sporadic errors of the following kind:
filename.json: openFile: resource busy (file is locked)
If somebody knows how to fix this catch22, I would really appreciate it. Thanks!
CodePudding user response:
Instead of forcing the result after closing the handle, you should force the result before closing the handle, here's how you can do that with BangPatterns
:
loadFromFile filename = do
fileHandle <- openFile ( dataDir "/" filename ) ReadMode
contents <- B.hGetContents fileHandle
let !result = fromMaybe initial $! JSON.decode contents
hClose fileHandle
return result
In this case a deepseq is not required, because (I believe) the decode
function will process the whole input before deciding whether to return Nothing
or Just ...
, so forcing only that one level is enough.
And, if possible, it is better to avoid handles entirely:
loadFromFile filename = do
contents <- B.readFile ( dataDir "/" filename )
return $! fromMaybe initial $! JSON.decode contents