Exception handling in GHC
Dean Herington
heringto@cs.unc.edu
Fri, 24 Jan 2003 18:58:14 -0500 (EST)
On Fri, 24 Jan 2003, Sarah Thompson wrote:
> I've noticed some interesting behaviour:
>
> Prelude Control.Exception> try (return (error "e"))
> Prelude Control.Exception> it
> Right *** Exception: e
>
> It would appear that when the result of this function is evaluated, the
> exception fires during evaluation, after the try is out of scope. I suppose
> it makes some kind of twisted sense due to lazy evaluation going on, but it
> is certainly a gotcha.
>
> I did notice this:
>
> Prelude Control.Exception> try (return $! (error "e"))
> Prelude Control.Exception> it
> Left e
>
> Seemingly, forcing strict evaluation on the argument of return fixes the
> problem by making sure that any exception that *can* happen, *does* happen.
>
> However, this code from my COM wrapper:
>
> --[id(3)] HRESULT XmlQuery([in,string] BSTR query, [out,retval]BSTR* xml);
> xmlQuery :: String -> State -> IO String
> xmlQuery qry (State st) = do
> db <- readIORef st
> Control.Exception.catch (return $! (XMLDatabase.xmlQuery qry db))
> (\ _ -> return "<error description=\"Parse
> error\"/>")
>
> doesn't work. If XMLDatabase.xmlQuery throws an exception, the COM wrapper
> still terminates the host application (Yes, Sigbjorn - I did apply your
> patch to HDirect, but it seemed to make no difference).
Your COM wrapper code probably behaves differently because the error is
not evoked at the very top level. Note that `seq` (and hence ($!)) only
force evaluation to "weak head normal form", which essentially means only
enough to determine the top-level constructor. You may need to evaluate
more deeply. Check out `DeepSeq`
(http://haskell.org/pipermail/haskell/2001-August/001586.html) and/or
"strategies"
(http://www.mail-archive.com/haskell@haskell.org/msg09543/Strategies.lhs).
> I'm still a bit stuck here!
>
> Sarah
Dean