[GHC] #10431: EqualityConstraints extension?

#10431: EqualityConstraints extension? -------------------------------------+------------------------------------- Reporter: adamgundry | Owner: Type: feature | Status: new request | Milestone: 7.12.1 Priority: normal | Version: 7.11 Component: Compiler | Operating System: Unknown/Multiple (Type checker) | Type of failure: None/Unknown Keywords: | Blocked By: Architecture: | Related Tickets: Unknown/Multiple | Test Case: | Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- At the moment, writing an equality constraint in a type requires at least one of the `GADTs` or `TypeFamilies` extensions. However, each of these has other effects. Could we have an `EqualityConstraints` extension to permit equality constraints in types, but neither GADTs nor type families? Presumably this extension should imply `MonoLocalBinds`. The `GADTs` extension could then become precisely the conjunction of `GADTSyntax`, `EqualityConstraints` and `ExistentialQuantification`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10431 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10431: EqualityConstraints extension? -------------------------------------+------------------------------------- Reporter: adamgundry | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.12.1 Component: Compiler (Type | Version: 7.11 checker) | Keywords: Resolution: | Architecture: Operating System: Unknown/Multiple | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by simonpj): Yes, that'd be quite possible. I'm not altogether sure it's worth the bother, but if someone wants to do it (and document it), I'd be OK with that. Simon -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10431#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10431: EqualityConstraints extension? -------------------------------------+------------------------------------- Reporter: adamgundry | Owner: Type: feature request | Status: new Priority: normal | Milestone: 8.0.1 Component: Compiler (Type | Version: 7.11 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by monoidal): I like this idea, however, a proper implementation will have some consequences. Can you review? The intended result is that GADTs becomes a synonym for three extensions (GADTSyntax, EqualityConstraints and ExistentialQuantification), and the compiler never checks for -XGADTs, but always for one of the three flags. 1) Make GADTs imply ExistentialQuantification This will mean that GADTs will enable syntax `data A = forall a. A a`. 2) Add EqualityConstraints extension This extension will imply `MonoLocalBinds` and be implied by `GADTs` and `TypeFamilies`. It will be checked in `check_eq_pred`. The remaining work is removing two places where the compiler reads `-XGADTs` flag. 3) Allow pattern matches on GADTs without `-XGADTs` Currently pattern matching on GADTs requires `-XGADTs` or `-XTypeFamilies` due to #2905. This restriction was made due to `-XRelaxedPolyRec` flag. However, `-XRelaxedPolyRec` cannot be disabled since GHC 7.0, the original motivation is lost. I suggest to remove the check altogether - generally we check for flags at definition sites but not call sites. 4) Check for EqualityConstraints when defining a GADT This step is optional and I'm not sure about it. Consider this code {{{ {-# LANGUAGE GADTSyntax, ExistentialQuantification #-} data Eq a b where Eq :: Eq a a }}} Currently this code compiles, however, it might be argued that `-XEqualityConstraints` is needed here, since the same datatype in non- GADT syntax requires it (`data Eq a b = a ~ b => Eq`) and `-XGADTSyntax` is not supposed to add extra expressiveness. However, this change is not backwards compatible and would probably require a deprecation period. The rule would be that existentials and contexts require `-XExistentialQuantification`, but if there is a specialized result type it would require both `-XExistentialQuantification` and `-XEqualityConstraints`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10431#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10431: EqualityConstraints extension? -------------------------------------+------------------------------------- Reporter: adamgundry | Owner: Type: feature request | Status: new Priority: normal | Milestone: 8.0.1 Component: Compiler (Type | Version: 7.11 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by adamgundry): Thanks for thinking through the implications of this! I'm now not sure that the principle I articulated (`GADTs = GADTSyntax + ExistentialQuantification + EqualityConstraints`) is essential. My instinctive reactions are: 1. Perhaps it would be better if this still required `ExistentialQuantification`, i.e. `GADTs` would enable existential GADTs but not plain existential datatypes? 2. Yes. 3. I'm in two minds about this. I know our general policy is to require flags only at definition sites, but type refinement on pattern matching is the whole point of GADTs, and is significantly different to non-GADT matching, so it seems like it is reasonable to mark the use sites as well. Perhaps GADT pattern matches should require `EqualityConstraints` (and hence `GADTs` would suffice)? 4. I'm surprised that `GADTs` is not required in your example: my vote is to treat it as a bug and fix it without a deprecation period. I'd expect `GADTSyntax + ExistentialQuantification` to allow data constructors with existential variables and contexts, but not specialized result types. I don't particularly mind whether this declaration is or is not accepted by `GADTSyntax + ExistentialQuantification + EqualityConstraints` without `GADTs`. I'd be interested to hear what others think. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10431#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10431: EqualityConstraints extension? -------------------------------------+------------------------------------- Reporter: adamgundry | Owner: Type: feature request | Status: new Priority: normal | Milestone: 8.0.1 Component: Compiler (Type | Version: 7.11 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by monoidal): Ad 1: The `data A = forall a. A a` syntax is enabled by `ExplicitForAll` + `GADTs` or by `ExistentialQuantification` (which implies `ExplicitForAll`). I imagine having explicit foralls is a feature separate from GADTs, so I see your point. The way I think about this is {{{ ExistentialQuantification = ExplicitForAll + existentials GADTs = GADTSyntax + EqualityConstraints + existentials }}} We could have a flag "existentials" (which would be useless without ExplicitForAll or GADTSyntax) but it does not seem to be worth it. I suggest that whenever the compiler needs to check for existentials it would check whether either `ExistentialQuantification` or `GADTs` is enabled. This way we have the equality `GADTs = ExistentialQuantification + EqualityConstraints + GADTSyntax` except that the right hand side also implies `ExplicitForAll`. Ad 3: I think making GADT pattern matches require `-XEqualityConstraints` is a step in right direction. However, the current check in `TcPat` has holes in it. For example, consider {{{ {-# LANGUAGE GADTs, MultiParamTypeClasses, FlexibleInstances #-} module X where class a ~ b => Equal a b instance Equal a a data E a b = Equal a b => E }}} {{{ module Y where import X f :: E a b -> a -> b f E x = x }}} This compiles as of current GHC, and introduces type equality in module Y without -XGADTs. (If you change the definition of `E` to `data E a b = a ~ b => E`, GHC will ask you to enable `-XGADTs`). Is this example a cheap trick or does it show a deeper problem? If we keep the check, I'd like to have a clear definition when a flag is required. Ad 4: I would prefer if the declaration was accepted with `GADTSyntax + ExistentialQuantification + EqualityConstraints`, because this way the flag `GADTs` would have clearer semantics. Otherwise we would have a distinction between `Eq :: a ~ b => Eq a b` and `Eq :: Eq a a`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10431#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10431: EqualityConstraints extension? -------------------------------------+------------------------------------- Reporter: adamgundry | Owner: Type: feature request | Status: new Priority: normal | Milestone: 8.0.1 Component: Compiler (Type | Version: 7.11 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by adamgundry): 1. Sounds good to me. I think this is probably already the case. The "existentials" flag can be spelled `-XExistentialQuantification -XNoExplicitForAll` and it is indeed useless; here's a poor if obscure error message: {{{ Prelude> set -XExistentialQuantification -XNoExplicitForAll Prelude> data T = forall a . MkT a <interactive>:3:10: Not a data constructor: ‘forall’ Perhaps you intended to use ExistentialQuantification }}} 3. Hmm, this is an interesting point. The current specification is something like this: `GADTs` (or `TypeFamilies`, and perhaps in the future `EqualityConstraints`) is required if pattern matching on a constructor whose context (at the type at which the pattern is being checked) directly includes a nominal equality. Here's another curious example: {{{#!hs data Dict c where MkDict :: c => Dict c f :: Dict (Int ~ Bool) -> Bool f MkDict = True -- requires GADTs g :: Dict a -> Bool g MkDict = True -- doesn't }}} I don't think we should do constraint solving to determine whether an extension is required by a pattern match. So perhaps it's better not to check at all. (But I wouldn't mind terribly if we retain the check as-is.) 4. Fair enough. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10431#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10431: EqualityConstraints extension? -------------------------------------+------------------------------------- Reporter: adamgundry | Owner: Type: feature request | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler (Type | Version: 7.11 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by RyanGlScott): * cc: RyanGlScott (added) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10431#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10431: EqualityConstraints extension? -------------------------------------+------------------------------------- Reporter: adamgundry | Owner: Type: feature request | Status: new Priority: normal | Milestone: 8.4.1 Component: Compiler (Type | Version: 7.11 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * milestone: 8.2.1 => 8.4.1 Comment: This won't be happening for 8.2. Bumping to 8.4. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10431#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10431: EqualityConstraints extension? -------------------------------------+------------------------------------- Reporter: adamgundry | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: 8.4.1 Component: Compiler (Type | Version: 7.11 checker) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by AntC): However this gets resolved, please doco which extensions enable the `(~)` syntax. Currently at 8.0.1: * Section 10.14.1 'Equality Constraints' tells how to use `(~)`, but not how to enable it. * Section 10.8.3.3 'Relaxed rules for instance contexts' mentions -XGADTs or -XTypeFamilies, as an aside.\\I'd call that a less than obvious place to look. It's not too bad: if you use `(~)` without either of those switched on, GHC's error message is very clear. (See this post https://mail.haskell.org/pipermail/glasgow-haskell- users/2017-April/026521.html.) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10431#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC