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
