
On Mon, 27 Jun 2011 12:39:42 +0900
Antoine Latter
On Mon, Jun 27, 2011 at 11:57 AM, Manfred Lotz
wrote: On Sun, 26 Jun 2011 17:32:02 -0400 David Place
wrote: On Jun 26, 2011, at 4:59 PM, Manfred Lotz wrote:
Is there any problem in the code snippet I pasted? If so I would like to get a hint of course.
There really isn't enough code in your snippet to be able to say. The rule is that if you return a lazy data structure from withFile you may find the file has been closed before you have read the data. If your parseXMLDoc is strict then you will get away with it. I feel that isn't very nice.
What I had learned (and it seems to work fine) is to force the result which gets done here in return $!
insertXml (stat, m) xf = U.withBinaryFile xf ReadMode (\handle -> do ct <- getXmlContent xf handle ... some code... return $! (stat',m'))
So I hope that is the one and important recipe to add when using withBinaryFile.
The operator ($!) isn't recursive, so all that it does is force the tuple you're returning, not the contents of the tuple.
Hmm, you are right.
Internally it calls 'seq', which only forces its argument enough to determine which constructor it was called with. Sometimes this can be enough to do what you want, but not usually. And certainly not in this case.
I tried now: getXmlContent :: String -> Handle -> IO Ctan getXmlContent xf inh = do xml <- U.hGetContents inh let content = xml `deepseq` parseXMLDoc xml case content of ... deepseq really ensures parseXmlDoc gets the full file as a string. It is unclear to me how this could be done without deepseq. -- Manfred