
Greetings, I've been thinking about bang patterns as part of implementing our own Haskell-like compiler here, and have been testing out GHC's implementation to see how it works. I've come to one case that seems like it doesn't work how I think it should, or how it is described, and wanted to ask about it. Specifically, consider: case Nothing of !(~(Just x)) -> 5 Nothing -> 12 Now, the way I'd expect this to work, and how I think the spec says it works, is that my Nothing is evaluated, and then the irrefutable ~(Just x) matches Nothing, giving a result of 5. In fact, GHC warns about overlapping patterns for this. However, this actually evaluates to 12, meaning that !(~p) appears to cancel out and be equivalent to p. It seems to me this might be a side effect of the logic used to implement 'let !p = ...', but I'm not certain. So, my question is whether this is intentional. If it is, then the bang patterns description should probably mention it, since it's subtly different than the rest of the specification. Also the warning should be removed, because there is no overlapping in the above case statement. If it is unintentional, we should probably decide either to make it intentional (and perform the above changes), or to change the implementation. :) Cheers, -- Dan

On Tue, Apr 1, 2014 at 3:02 PM, Dan Doel
Specifically, consider:
case Nothing of !(~(Just x)) -> 5 Nothing -> 12
Now, the way I'd expect this to work, and how I think the spec says it works, is that my Nothing is evaluated, and then the irrefutable ~(Just x) matches Nothing, giving a result of 5. In fact, GHC warns about overlapping patterns for this.
It's sensible to give an overlap warning --that is, assuming we don't want overlap to be an error-- since the irrefutable pattern matches everything, and adding bangs doesn't change what values are matched (it only changes whether we diverge or not). However, I have no idea how top-level bang in case-expressions is supposed to be interpreted. If anything, it should be ignored since we must already force the scrutinee to WHNF before matching *any* of the clauses of a case-expression. However, I thought bangs were restricted to (1) immediately before variables, and (2) for top-level use in let/where clauses... In any case, following the standard desugaring of the specs: case Nothing of !(~(Just x)) -> 5 ; Nothing -> 12 === { next to last box of http://www.haskell.org/ghc/docs/latest/html/users_guide/bang-patterns.html, the proposed clause (t) for section 3.17.3, figure 4 } Nothing `seq` case Nothing of ~(Just x) -> 5 ; Nothing -> 12 === { Haskell Report, section 3.17.3, figure 3, clause (d) } Nothing `seq` (\x -> 5) (case Nothing of Just x -> x) Which most definitely does not evaluate to 12. Either the specs are wrong (dubious) or the implementation is. File a bug report. -- Live well, ~wren

Filed. Bug #8952.
On Wed, Apr 2, 2014 at 3:41 PM, wren romano
On Tue, Apr 1, 2014 at 3:02 PM, Dan Doel
wrote: Specifically, consider:
case Nothing of !(~(Just x)) -> 5 Nothing -> 12
Now, the way I'd expect this to work, and how I think the spec says it works, is that my Nothing is evaluated, and then the irrefutable ~(Just x) matches Nothing, giving a result of 5. In fact, GHC warns about overlapping patterns for this.
It's sensible to give an overlap warning --that is, assuming we don't want overlap to be an error-- since the irrefutable pattern matches everything, and adding bangs doesn't change what values are matched (it only changes whether we diverge or not).
However, I have no idea how top-level bang in case-expressions is supposed to be interpreted. If anything, it should be ignored since we must already force the scrutinee to WHNF before matching *any* of the clauses of a case-expression. However, I thought bangs were restricted to (1) immediately before variables, and (2) for top-level use in let/where clauses...
In any case, following the standard desugaring of the specs:
case Nothing of !(~(Just x)) -> 5 ; Nothing -> 12
,
=== { next to last box of < http://www.haskell.org/ghc/docs/latest/html/users_guide/bang-patterns.html the proposed clause (t) for section 3.17.3, figure 4 }
Nothing `seq` case Nothing of ~(Just x) -> 5 ; Nothing -> 12
=== { Haskell Report, section 3.17.3, figure 3, clause (d) }
Nothing `seq` (\x -> 5) (case Nothing of Just x -> x)
Which most definitely does not evaluate to 12. Either the specs are wrong (dubious) or the implementation is. File a bug report.
-- Live well, ~wren
participants (2)
-
Dan Doel
-
wren romano