haskell / error-messages

71 stars 18 forks source link

Incorrect usage of the term "bang-pattern" #36

Open MorrowM opened 2 years ago

MorrowM commented 2 years ago

Given the following module:

module Bang where

z = let !(x,y) = (1,2) in x

We get the following error message:

Bang.hs:3:9: error:
    Illegal bang-pattern (use BangPatterns):
    ! (x, y)
  |
3 | z = let !(x,y) = (1,2) in x
  |         ^^^^^^

which is incorrect, this is a strict binding, not a bang pattern.

Suggested error message:

Bang.hs:3:9: error:
    Illegal strict binding (use BangPatterns):
    ! (x, y)
  |
3 | z = let !(x,y) = (1,2) in x
  |         ^^^^^^
goldfirere commented 2 years ago

Hooray! I think you should just go ahead and post this as a GHC bug with exactly your suggested fix. It always makes me happy to see someone distinguish between bang patterns and strict bindings. They are not the same -- though it's very understandable why some people think they are!

MorrowM commented 2 years ago

https://gitlab.haskell.org/ghc/ghc/-/issues/21032

Ericson2314 commented 2 years ago

I wonder if we might want to change our terminology too.

Syntactically, it's hard to tell people patterns are compositional, pat ::= ! <pat> | ... and yet !(x,y) here is not a bang pattern.

The fact the outer ! _ means something else is necessary once one really thinks hard about semantics (and we still debate this stuff, e.g. in https://github.com/ghc-proposals/ghc-proposals/pull/35 !) is hard to tell beginners, especially as the overall message of Haskell is "we can do more with a few very compositional things than you might expect"

I think I would prefer we had a "syntactic" name for all ! <pat> things, and then separate "semantic" names for the outer vs inner cases.

This specific error is purely at the syntactic level, so we don't need to worry about the semantic distinction, which will just add confusion especially as learning semantic concepts about disabled extensions should never be necessary.

goldfirere commented 2 years ago

I don't really understand what you're getting at @Ericson2314. I think we have done exactly what you suggest: we distinguish between a strict binding and a bang pattern. Or is there more to the story than that?

Ericson2314 commented 2 years ago

@goldfirere I mean I want both:

The first I am calling the syntactic one, and the second I am calling the semantics ones.


Anyone that doesn't know what bang patterns are / strictness is, is not going to think

let !((x, y), z) = ...

and

let (!(x, y), z) = ...

are meaningfully different.

In the spirit of "users should not have to be aware of the extensions they don't use", I would like both to give the same error when PatternSynonyms BangPatterns is disabled. And so far that we the single "syntactic" jargon term.

goldfirere commented 2 years ago

I think you meant BangPatterns in your last line. Assuming so, can I rephrase your argument as this:

Does that capture what you're suggesting?

If so, I now understand, but I disagree: I would rather use the opportunity to teach the user something new. If they discover that GHC names !((x,y), z) = ... differently from (!(x,y), z) = ..., then they have the opportunity to look up these constructs and understand what they do. I think it's actually a small mis-design that the syntax is so similar between these two (made even worse by the fact that the semantics are also similar -- but not identical!), and so calling these out with two different names can help to educate our users who must suffer with the mis-design.

That said, I do see your point here, too, in that we're introducing a source of complexity where it was less apparent previously.

Ericson2314 commented 2 years ago

@goldfirere I like your proposed message! That does accomplish the goal.

I do think if ! = bang, "! in a pattern" sounds like a synonym for "bang pattern", but maybe we can say "strict binding" and "strict nested pattern?" Then the syntact one has "bang" and the semantic ones have "strict"

I do agree re fostering curiosity and re unfortunate that the syntax is overloaded. But I think

  1. Extension is called BangPatterns
  2. Error message when BangPatterns is disabled says ! in a pattern implied correspond 1-1 with "bang pattern"
  3. Error messages with BangPatterns enabled and in GHC Users Guide about extension exclusively uses "strict binding" and "strict nested pattern" to emphasize distinction.

Achieves all goals? In particular, with BangPatterns enabled, the user would not see "! in pattern" and "bang pattern" since it is wrong to conflate the two now that the semantics are "in scope".

goldfirere commented 2 years ago

There's one problem: do we ever use this language when BangPatterns is enabled? I don't think we do, and so we've lost our opportunity to educate.

Ericson2314 commented 2 years ago

If you like those terms, I suppose we can just grep through the code base and see where they show up, and where "bang pattern" perhaps can be replaced with something better. I would hope there are diagnostics that can be adapted to say "strict ...".

goldfirere commented 2 years ago

I still favor just using the correct, full terms even when BangPatterns is not on. Do any others here have an opinion?

Ericson2314 commented 2 years ago

Ah, I see I misread --- you don't actually like your phrasing of my idea "Illegal pattern: Use of ! in a pattern requires BangPatterns" as a first choice. I do like it, but fair enough. I at least understand now.