[GHC] #8171: Extending ExtendedDefaultRules

#8171: Extending ExtendedDefaultRules ------------------------------------+------------------------------------- Reporter: ekmett | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Keywords: | Operating System: Unknown/Multiple Architecture: Unknown/Multiple | Type of failure: None/Unknown Difficulty: Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | ------------------------------------+------------------------------------- The current `ExtendedDefaultRules` is set up in a way that largely prevents it from being used for scenarios beyond what they get used for in GHCi today. It would be great if there was an extra class that could be included in the list of acceptable classes for Rule 3. {{{ class Defaulting a }}} The proposed change would be that Rule 3 under EDR can be be relaxed to: At least one of the classes Ci is numeric, or is `Show`, `Eq`, `Ord` or `Defaulting`. I went with `Defaulting` rather than `Default`, because `Default` is a common class in use across the ecosystem from the `data-default` package, and I wanted to avoid gratuitous fallout. This would permit projects like Shae Erisson's `ghclive` from last year that need to use defaulting to not have to shoe-horn unnecessary `Show` constraints onto functions. Even better would be for that class to be polykinded! That opens up possibilities for expert users to get defaulting to fire on arguments of other kinds, which is impossible under the current EDR. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------ Reporter: ekmett | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Changes (by ekmett): * cc: ekmett@… (added) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------ Reporter: ekmett | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Description changed by simonpj: Old description:
The current `ExtendedDefaultRules` is set up in a way that largely prevents it from being used for scenarios beyond what they get used for in GHCi today.
It would be great if there was an extra class that could be included in the list of acceptable classes for Rule 3.
{{{ class Defaulting a }}}
The proposed change would be that Rule 3 under EDR can be be relaxed to: At least one of the classes Ci is numeric, or is `Show`, `Eq`, `Ord` or `Defaulting`.
I went with `Defaulting` rather than `Default`, because `Default` is a common class in use across the ecosystem from the `data-default` package, and I wanted to avoid gratuitous fallout.
This would permit projects like Shae Erisson's `ghclive` from last year that need to use defaulting to not have to shoe-horn unnecessary `Show` constraints onto functions.
Even better would be for that class to be polykinded!
That opens up possibilities for expert users to get defaulting to fire on arguments of other kinds, which is impossible under the current EDR.
New description: The current `ExtendedDefaultRules` (see [http://www.haskell.org/ghc/docs/latest/html/users_guide/interactive- evaluation.html#extended-default-rules manual page]) is set up in a way that largely prevents it from being used for scenarios beyond what they get used for in GHCi today. It would be great if there was an extra class that could be included in the list of acceptable classes for Rule 3. {{{ class Defaulting a }}} The proposed change would be that Rule 3 under EDR can be be relaxed to: At least one of the classes Ci is numeric, or is `Show`, `Eq`, `Ord` or `Defaulting`. I went with `Defaulting` rather than `Default`, because `Default` is a common class in use across the ecosystem from the `data-default` package, and I wanted to avoid gratuitous fallout. This would permit projects like Shae Erisson's `ghclive` from last year that need to use defaulting to not have to shoe-horn unnecessary `Show` constraints onto functions. Even better would be for that class to be polykinded! That opens up possibilities for expert users to get defaulting to fire on arguments of other kinds, which is impossible under the current EDR. -- -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------ Reporter: ekmett | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by simonpj): Would you like to elaborate a couple of use-cases? What types would be instances of `Defaulting`? Would one person's use of `Defaulting` mess up another's? Simon -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------ Reporter: ekmett | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by ekmett): No more so than someone's instance of `Show` messing up another's. Consider Shae Erisson's `ghclive` from last year's GSoC. There we're running a ghci analogue in the web browser, but we want to support doing things like rendering diagrams using Brent Yorgey's diagrams tool, so we have our own class of things we can show on the web. {{{ class Display a where displayList :: [a] -> DisplayResult displayList = displayListOf display display :: a -> DisplayResult default display :: (Generic a, GDisplay (Rep a)) => a -> DisplayResult display = gdisplay . from }}} This is very much like `Show`, but it an include embedded images, hyperlinks, etc. as it is ultimately destined for the web. We can tell hint to infer for it by wrapping whatever expression we get from the user in a call to `display`, but it won't do defaulting. To fool `hint` into defaulting we have to add a completely unnecessary constraint to the environment to make the call elegible for defaulting! Of those, Show is the most innocuous, so we instead have to {{{ displaying :: (Display a, Show a) => a -> DisplayResult displaying = display }}} We then infer for it by wrapping the expression the user supplied in a 'displaying' call. https://github.com/shapr/ghclive/blob/master/src-main/Main.hs#L214 But that is a lie. We don't need Show. We don't want Show. We just need to fake Show even for a number of un-Show-able things like diagrams to make GHC happy. Worse, the `displaying` function used to have to be a separate function rather than be placed as a superclass of `Display` because GHC wouldn't rummage through the superclasses when figuring out if extended defaulting should fire, so we not only had to have an unnecessary Show constraint, but it had to be on the 'outside' of the current constraint set. That issue appears to have since been fixed though, so it should be possible with the addition of Defaulting to say: {{{ class Defaulting a => Display a where }}} or to say the more targeted: {{{ display :: (Display a, Defaulting a) => a -> DisplayResult }}} I'm open to other solutions. The instance seems somewhat clunky. In many ways maybe what you really kind of want is something like the roles annotations where you annotate the class arguments you want to allow defaulting on. That may be a way to address the current discussion about `IsString`, and could be a vehicle for enabling limited defaulting in the presence of MPTCs, but it was a lot more engineering effort than I felt comfortable asking for! =) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------ Reporter: ekmett | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by simonpj): The extended-default rules for a bunch of constraints (C1 a1, C2 a2, ...) are these: 1. The type variable a appears in no other constraints 2. All of the classes Ci are single-parameter type classes. 3. At least one of the classes Ci is numeric, or is Show, Eq, or Ord. We could, I suppose, relax it by simply abolishing Rule 3. That would certainly solve your problem, and would require little engineering effort. I don't know what the unintended consequences might be. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------ Reporter: ekmett | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by ekmett): Personally, I think that sounds like a pretty good fix. I'd want to float it past the libraries mailing list to see what issues folks can foresee, but literally none of the packages I maintain on hackage would have an issue with this change, but you already get a warning with -Wall for defaulting, and all programs that typechecked before would necessarily continue to typecheck, more defaulting would work by default in future code though. This interacts with the current libraries discussion on how to improve the rules about the shape of constraints (C1 a1, ...) to make it possible to support defaulting IsString when something like `length "hello"` on an OverloadedString happens. With appropriate rephrasing of the conditions on the constraints above, we may be able to consolidate support both of these scenarios. That said, I'm not sure off the top of my head how to rephrase that condition on the initial batch of constraints. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------ Reporter: ekmett | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by simonpj): Fine with me. I just want to advertise that the EDR rules are not a deep property of type system. They are rather ad-hoc, driven by user need, and are modularly separated from the rest of type inference. So you are entirely free to propose different ones! Simon -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------ Reporter: ekmett | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: None/Unknown | Difficulty: Unknown Test Case: | Blocked By: Blocking: | Related Tickets: -------------------------------------+------------------------------------ Comment (by ekmett): FWIW- We've been using a simpler system just like the one you proposed in our compiler for a Haskell-like language at work since its inception a couple of years ago with no user issues. We did so mostly because we couldn't be bothered to come up with a more complex system of rules. https://github.com/ermine-language/ermine- legacy/blob/948a053b6f9ea274d11bf34cb2e3a9c7f3937923/src/main/scala/com/clarifi/reporting/ermine/Subst.scala#L382 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------- Reporter: ekmett | Owner: kanetw Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by kanetw): * owner: => kanetw -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------- Reporter: ekmett | Owner: kanetw Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by kanetw): I'll be taking a look at this. Probably going to write a paper about the implementation, too. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:10 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------- Reporter: ekmett | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by kanetw): * owner: kanetw => Comment: Currently don't have the time for this, but I might revisit this later. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:11 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------- Reporter: ekmett | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: | ExtendedDefaultRules Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #2641 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by thomie): * keywords: => ExtendedDefaultRules * related: => #2641 Comment: Replying to [comment:5 simonpj]:
The extended-default rules for a bunch of constraints (C1 a1, C2 a2, ...) are these: 1. The type variable a appears in no other constraints 2. All of the classes Ci are single-parameter type classes. 3. At least one of the classes Ci is numeric, or is Show, Eq, or Ord.
We could, I suppose, relax it by simply abolishing Rule 3.
See also #2641 (still open), where you proposed to make these rules //less// liberal, albeit 7 years ago. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:12 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------- Reporter: ekmett | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: | ExtendedDefaultRules Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #2641 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by crockeea): * cc: ecrockett0@… (added) Comment: Also see #12271. My primary concern there is GHC rather than GHCi. My main point there is: users should be able to specify defaults for user-defined /non-Prelude constraints; defaulting should not be a magical property baked into specific Prelude typeclasses. It sounds like the solution proposed here would require -XEDR, whereas my proposed solution just modifies the existing `default` tuple, similar to what Edward suggested at the end of [https://ghc.haskell.org/trac/ghc/ticket/8171#comment:4 comment 4]. I think removing rule 3 from the EDRs would effectively remove the "magic" that I talk about in that ticket. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:13 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#8171: Extending ExtendedDefaultRules -------------------------------------+------------------------------------- Reporter: ekmett | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.6.3 Resolution: | Keywords: | ExtendedDefaultRules Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #2641 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by mentheta): * cc: mentheta (added) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8171#comment:14 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC