Re: [GHC] #1171: GHC doesn't respect the imprecise exceptions semantics
#1171: GHC doesn't respect the imprecise exceptions semantics --+- Reporter: neil | Owner: Type: bug | Status: reopened Priority: low | Milestone: _|_ Component: Compiler |Version: 6.6 Severity: normal| Resolution: Keywords:| Difficulty: Unknown Testcase: cg059 | Architecture: Multiple Os: Multiple | --+- Comment (by Isaac Dupree): Stefan O'Rear happened to write in haskell-cafe a performance reason for allowing non-termination to throw any exception: When you see an expression of the form: f a you generally want to evaluate a before applying; but if a is _|_, this will only give the correct result if f a = _|_. Merely 'guaranteed to evaluate' misses out on some common cases, for instance ifac: {{{ ifac 0 a = a ifac n a = ifac (n - 1) (a * n) }}} ifac is guaranteed to either evaluate a, or go into an infinite loop - so it can be found strict, and unboxed. Whereas 'ifac -1 (error moo)' is an infinite loop, so using a definition based on evaluation misses this case. -- Ticket URL: http://hackage.haskell.org/trac/ghc/ticket/1171#comment:13 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler___ Glasgow-haskell-bugs mailing list Glasgow-haskell-bugs@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs
Re: [GHC] #1171: GHC doesn't respect the imprecise exceptions semantics
#1171: GHC doesn't respect the imprecise exceptions semantics --+- Reporter: neil | Owner: Type: bug | Status: reopened Priority: low | Milestone: _|_ Component: Compiler |Version: 6.6 Severity: normal| Resolution: Keywords:| Difficulty: Unknown Testcase: cg059 | Architecture: Multiple Os: Multiple | --+- Comment (by igloo): The below is from e-mail and IRC conversations that happened in parallel with this bug report. I've editted things slightly to make them flow better, but hopefully haven't changed any important meanings. __I said:``__ In http://research.microsoft.com/~simonpj/Papers/imprecise-exn.htm I think you claim in section 4.3, in the rationale for the Bad case, that if we have {{{ f x = case x of True - error A False - error B }}} then the call {{{ f (error X) }}} is allowed to raise B, as this permits transformations like {{{ f' x = let b = error B in b `seq` case x of True - error A False - b }}} which in turn is justified because the case expression is strict in {{{ error B }}} (as well as every other expression). However, the Ok case tells me that if I call {{{ f True }}} then I can get the errors raised by the {{{ True - error A }}} branch only. Thus it must raise A. But with the above transformation f' raises B. I also think that this behaviour is very confusing to users; it makes sense that {{{ error A + error B }}} needs to evaluate both values, so throwing either exception is reasonable, but in {{{ f True }}} it is obvious that A is raised and B is not! Traditionally, we would say that e is strict in x if {{{ x = _|_=e = _|_ }}} However, with the set-based imprecise exceptions, in which we distinguish between different bottoms, it seems to me that a better definition would be that e is strict in x if {{{ x = Bad xs=e = Bad ys and xs \subseteq ys }}} Thus, for example, a case can throw an exception if either the scrutinee can or /all/ the branches can, i.e. in the Bad case in 4.3 we take the big intersection rather than big union. So we wouldn't be allowed to pull {{{ error B }}} out of the above case, but we would still be able to translate {{{ case x of True - y False - y }}} into {{{ y `seq` case x of True - y False - y }}} I am also unconvinced by a non-terminating program being allowed to throw anything it likes. It seems much nicer to permit it only to either not terminate or to throw a special exception, here-on written N. I haven't written a denotational semantics or anything, so perhaps this would all unravel if I tried, but here are some example definitions followed by what exceptions I think various expressions ought to be able to throw; are there any obvious nasty corners I have left unexplored?: {{{ f x = case x of True - error A False - error B g x = case x of True - error C False - error C h () () = () i = i j = error D + j - f True A f (error E) E g True C g (error F) C or F h (error G) (error H) G or H i N or non-termination j D, N or non-termination }}} I also haven't looked into the performance implications, although personally I'd prefer a semantics that is more intuitive along with a few more bang patterns sprinkled around. __Simon PJ replied:``__ I think you are basically right here. Another way to say it is this. In 4.5 we claim that GHC's transformations can reduce the set of possible exceptions from a term, but not increase it. But the (current) strictness analysis transformation increases it. I agree that is undesirable. As I say on the Trac, we could change this at the cost of making fewer functions strict. I can tell anyone how to do this, if you want. It would be good to measure the performance impact of doing so. __Simon M__ has a memory that there is some problem, possibly related to monotonicity, with only allowing non-terminating programs to either not terminate or throw a special non-termination error, rather than allowing them to behave like any bottom they wish as the imprecise exceptions paper allows them to. However, he can't remember what the problem actually is; if anyone can then it would be good to have it documented. Regarding __Simon PJ__``'s earlier comment {{{ It's easily stopped, too, by stopping GHC treating error like bottom; but that would make many
Re: [GHC] #1171: GHC doesn't respect the imprecise exceptions semantics
Hi In response to Neil: why use `unsafePerformIO` rather than IO exceptions here? I think you're asking for more trouble... Are you referring to ioError? My knowledge of exceptions in Haskell is limited. The error architecture is often a long way from the IO monad, so whatever we do can't require the IO monad. Thanks Neil ___ Glasgow-haskell-bugs mailing list Glasgow-haskell-bugs@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs
Re: [GHC] #1171: GHC doesn't respect the imprecise exceptions semantics
Neil Mitchell wrote: Hi In response to Neil: why use `unsafePerformIO` rather than IO exceptions here? I think you're asking for more trouble... Are you referring to ioError? My knowledge of exceptions in Haskell is limited. The error architecture is often a long way from the IO monad, so whatever we do can't require the IO monad. Yes - the example was in the IO monad so I thought you could use IO exceptions. In any case, I don't recommend using 'error' (or indeed 'unsafePerformIO') for errors you report to the user, purely because of its non-deterministic semantics. If you use a suitable error monad or IO exceptions, you can be sure that you'll get the same behaviour regardless of compiler or optimisation settings. Cheers, Simon ___ Glasgow-haskell-bugs mailing list Glasgow-haskell-bugs@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs
Re: [GHC] #1171: GHC doesn't respect the imprecise exceptions semantics
Hello, The code in YHC is roughly if some list is empty then error No files found else error Many files found. If this code were changed to the equivalent of error (if some list is empty then No files found else Many files found), would there still be circumstances where the actual output produced could vary? Thanks and best regards Thorkil On Wednesday 28 February 2007 12:31, Simon Marlow wrote: Neil Mitchell wrote: Hi In response to Neil: why use `unsafePerformIO` rather than IO exceptions here? I think you're asking for more trouble... Are you referring to ioError? My knowledge of exceptions in Haskell is limited. The error architecture is often a long way from the IO monad, so whatever we do can't require the IO monad. Yes - the example was in the IO monad so I thought you could use IO exceptions. In any case, I don't recommend using 'error' (or indeed 'unsafePerformIO') for errors you report to the user, purely because of its non-deterministic semantics. If you use a suitable error monad or IO exceptions, you can be sure that you'll get the same behaviour regardless of compiler or optimisation settings. Cheers, Simon ___ Glasgow-haskell-bugs mailing list Glasgow-haskell-bugs@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs ___ Glasgow-haskell-bugs mailing list Glasgow-haskell-bugs@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs
RE: [GHC] #1171: GHC doesn't respect the imprecise exceptions semantics
The code in YHC is roughly if some list is empty then error No files found else error Many files found. If this code were changed to the equivalent of error (if some list is empty then No files found else Many files found), would there still be circumstances where the actual output produced could vary? Maybe. If GHC knows that error is strict (which it might well do) then you could be back where you started. Cheers, Simon ___ Glasgow-haskell-bugs mailing list Glasgow-haskell-bugs@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs
Re: [GHC] #1171: GHC doesn't respect the imprecise exceptions semantics
Simon Marlow wrote: The code in YHC is roughly if some list is empty then error No files found else error Many files found. If this code were changed to the equivalent of error (if some list is empty then No files found else Many files found), would there still be circumstances where the actual output produced could vary? Maybe. If GHC knows that error is strict (which it might well do) then you could be back where you started. Oops, error isn't strict, never mind. Cheers, Simon ___ Glasgow-haskell-bugs mailing list Glasgow-haskell-bugs@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs
Re: [GHC] #1171: GHC doesn't respect the imprecise exceptions semantics
Simon Marlow wrote: Simon Marlow wrote: The code in YHC is roughly if some list is empty then error No files found else error Many files found. If this code were changed to the equivalent of error (if some list is empty then No files found else Many files found), would there still be circumstances where the actual output produced could vary? Maybe. If GHC knows that error is strict (which it might well do) then you could be back where you started. Oops, error isn't strict, never mind. Ok, so error *is* strict. Please ignore me, I have a cold and I'm having a bad day :-( Cheers, Simon ___ Glasgow-haskell-bugs mailing list Glasgow-haskell-bugs@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs