
A plea for DerivingStrategies: GHC currently chooses which strategy to use rather arbitrarily. (For example, did you know that Eq and Ord are derived by GeneralizedNewtypeDeriving whenever possible, even when that extension isn't enabled?) And Show is always derived by the `stock` strategy, even when GND is enabled (and otherwise possible). Instead, DerivingStrategies allows users to be explicit, and (in my opinion) should be a matter of good style, just like top-level type signatures. Having to enable the extension to use good style is an annoying hurdle. While the set of strategies may evolve, the idea of writing out strategies (and their syntax) feels stable to me. A plea for NamedWildCards: This feature allows type variables beginning with an underscore to be treated as a component in a partial type signature. Critically (for this plea), a type signature with a named wild card will not be accepted without -XPartialTypeSignatures. I do *not* advocate for -XPartialTypeSignatures! So, having -XNamedWildCards on simply means that we get an informative error message when the user writes a type variable beginning with an underscore. The only downside is that programs such as id :: _a -> _a are no longer accepted. But does anyone write type variables with leading underscores? If we think this is at all common, then I would change my mind here. Why have it on by default? Because it's not easily discoverable, and the error messages really are quite nice. A plea against MonoLocalBinds (and, hence, TypeFamilies): MonoLocalBinds is fork-like: it will mean that some Haskell98 programs will not be accepted. And to get those programs accepted, a user might need ScopedTypeVariables -- in specific, the aspect of ScopedTypeVariables that seems likeliest to change in the future. So I don't think we should have MonoLocalBinds on by default. Thanks for reading! Richard

Hi, Am Dienstag, den 08.12.2020, 03:47 +0000 schrieb Richard Eisenberg:
A plea for DerivingStrategies:
concur!
A plea for NamedWildCards:
concur!
A plea against MonoLocalBinds (and, hence, TypeFamilies): MonoLocalBinds is fork-like: it will mean that some Haskell98 programs will not be accepted. And to get those programs accepted, a user might need ScopedTypeVariables -- in specific, the aspect of ScopedTypeVariables that seems likeliest to change in the future. So I don't think we should have MonoLocalBinds on by default.
Looking at the stats, this has 279% contentiousness (2.7× as many “no” votes than “yes” votes in the popular vote). I am happy to follow your advice here (and, as always, a plea _against_ an extension is on its own almost enough to kill the extension, as it is by definition no longer uncontentious). Would you argue that it should not be included even _if_ we’d include GADTs and/or TypeFamilies? Or are you saying that MonoLocalBinds shouldn’t be in; GADTS/TypeFamilies are bad without MonoLocalBinds, and thus GADTs/TypeFamilies ought to be left out? cheers, Joachim -- Joachim Breitner mail@joachim-breitner.de http://www.joachim-breitner.de/

On Dec 8, 2020, at 4:32 AM, Joachim Breitner
wrote: Would you argue that it should not be included even _if_ we’d include GADTs and/or TypeFamilies? Or are you saying that MonoLocalBinds shouldn’t be in; GADTS/TypeFamilies are bad without MonoLocalBinds, and thus GADTs/TypeFamilies ought to be left out?
No. If we have GADTs and/or TypeFamilies, then we should absolutely have MonoLocalBinds -- GADTs and TypeFamilies are wonky without MonoLocalBinds. I'd prefer not to have any of them on by default.
On Dec 8, 2020, at 10:36 AM, Eric Seidel
wrote:
Aha, so what you're saying is that with NamedWildCards but not PartialTypeSignatures, GHC will tell you what `_a` was solved for, but it won't accept the resulting program? I didn't realize that NamedWildCards did anything in the absence of PartialTypeSignatures, but I agree that this is better. I was already voting for NamedWildCards, but now I'm inclined to additionally vote against PartialTypeSignatures.
Exactly, yes. I am strongly against PartialTypeSignatures as an extension, as users should have to opt into accepting partially-written programs.
On Dec 8, 2020, at 11:59 AM, Iavor Diatchki
wrote: It seems odd to turn on an extension [NamedWildCards] that doesn't do anything, and it is entirely there to make *another* extension work better? Wouldn't it be better to make `PartialTypeSignatures` imply `NamedWildCards`?
NamedWildCards *does* do something on its own -- it just doesn't accept new programs. If we consider
foo :: _a -> _a foo True = False foo False = True
Without NamedWildCards, we get
Bug.hs:4:5: error: • Couldn't match expected type ‘_a’ with actual type ‘Bool’ ‘_a’ is a rigid type variable bound by the type signature for: foo :: forall _a. _a -> _a at Bug.hs:3:1-15 • In the pattern: True In an equation for ‘foo’: foo True = False • Relevant bindings include foo :: _a -> _a (bound at Bug.hs:4:1)
With NamedWildCards, we get
Bug.hs:5:8: error: • Found type wildcard ‘_a’ standing for ‘Bool’ To use the inferred type, enable PartialTypeSignatures • In the type signature: foo :: _a -> _a
I think that prefixing a variable name with an underscore is a convenient, lightweight way of asking GHC to tell me what a type should be. Richard

On Tue, Dec 8, 2020 at 8:54 PM Richard Eisenberg
No. If we have GADTs and/or TypeFamilies, then we should absolutely have MonoLocalBinds -- GADTs and TypeFamilies are wonky without MonoLocalBinds. I'd prefer not to have any of them on by default.
Do we agree that this is not tenable in the long term? At some point, GADTs and TypeFamilies need to be in by default. When is that horizon? For context, these features have been with us for 12 years (since GHC 6.8.1). And quite stable in the last 6 years. They are not going anywhere, they are very widely used. Just as much, I'd say MonoLocalBinds really wants to be the default (supporting `NoMonoLocalBinds` at all probably has some non-trivial implementation costs, I would not be sad to see this go, even if it's a bit hard to get rid of in the current state because it does mean breaking compatibility with Haskell98 and Haskell2010, in fact, we still support `DatatypeContext` at the cost of code). Maybe GHC2021 shouldn't have these (it's not my opinion, but it's arguable). Since the value of GHC2021 is “conservatism” (then again, we seem to be adding in StandaloneKindSignatures and NamedFieldPuns, which do not sound very conservative to me). But then, they are the first two extensions that should be considered for GHC2022. Do we agree on this? Or would you rather see these stay in their standalone extensions forever? (which I would find, personally, rather alarming) Exactly, yes. I am strongly against PartialTypeSignatures as an extension,
as users should have to opt into accepting partially-written programs.
How is a partial type signature a partially-written program? Does the absence of type signature on a binding make a program partially written? Because a partial type signature is more than no signature at all, so it should be considered less partial at least. Plus, partial type signatures give a warning (which, I've argued before, is probably more than you actually want cf https://gitlab.haskell.org/ghc/ghc/-/issues/16220). I don't know that we want PartialTypeSignature this time around. And there may be reason to never want them. But I'd say “users should have to opt into accepting partially-written programs” is not one of them. With NamedWildCards, we get
Bug.hs:5:8: error: • Found type wildcard ‘_a’ standing for ‘Bool’ To use the inferred type, enable PartialTypeSignatures • In the type signature: foo :: _a -> _a
I think that prefixing a variable name with an underscore is a convenient, lightweight way of asking GHC to tell me what a type should be.
On the other hand, I think that I agree with this, and that I will change my vote.

Hi, Am Mittwoch, den 09.12.2020, 12:17 +0100 schrieb Spiwack, Arnaud:
Maybe GHC2021 shouldn't have these (it's not my opinion, but it's arguable). Since the value of GHC2021 is “conservatism” (then again, we seem to be adding in StandaloneKindSignatures and NamedFieldPuns, which do not sound very conservative to me). But then, they are the first two extensions that should be considered for GHC2022. Do we agree on this? Or would you rather see these stay in their standalone extensions forever? (which I would find, personally, rather alarming)
what I deduce from this discussion is that there is quite a lot of discussion to be had, and I’d prefer to have that next round. Let’s crawl before we walk, and get a GHC2021 out that nobody will object to. When it comes to GHC2022, we can focus on the harder ones. Plus there is one more year to ponder these issues in the back of our head. What I also got from this discussion was learning why sometimes a `where foo = 1000` works at different number types, and sometimes not. It depends on whether I am using GADTs or TypeFamilies somewhere in the file! Who’d have thought… cheers, Joachim -- Joachim Breitner mail@joachim-breitner.de http://www.joachim-breitner.de/

On Wed, Dec 9, 2020 at 5:40 AM Joachim Breitner
What I also got from this discussion was learning why sometimes a `where foo = 1000` works at different number types, and sometimes not. It depends on whether I am using GADTs or TypeFamilies somewhere in the file! Who’d have thought…
Actually `where foo = 1000` wouldn't be affected by `MonoLocalBinds` (but would be by the `MonomorphsimRestriction`, fun right :-) ). `MonoLocalBinds` only affects local bindings that depend on something from a pattern (i.e., declaration that you can't just move to the top level because they depend on something locally bound) -Iavor

Hi, Am Mittwoch, den 09.12.2020, 09:19 -0800 schrieb Iavor Diatchki:
On Wed, Dec 9, 2020 at 5:40 AM Joachim Breitner
wrote: What I also got from this discussion was learning why sometimes a `where foo = 1000` works at different number types, and sometimes not. It depends on whether I am using GADTs or TypeFamilies somewhere in the file! Who’d have thought…
Actually `where foo = 1000` wouldn't be affected by `MonoLocalBinds` (but would be by the `MonomorphsimRestriction`, fun right :-) ). `MonoLocalBinds` only affects local bindings that depend on something from a pattern (i.e., declaration that you can't just move to the top level because they depend on something locally bound)
Indeed! I confess ignorance… -- Joachim Breitner mail@joachim-breitner.de http://www.joachim-breitner.de/

On Dec 9, 2020, at 6:17 AM, Spiwack, Arnaud
wrote: Or would you rather see these stay in their standalone extensions forever? (which I would find, personally, rather alarming)
I'm attacking from the standpoint that these will be extensions forever -- or, at least until we have a specification of them. (Amazingly, we don't have a specification for either one, right now.) Haskell will always have new learners, and I think it's reasonable to guard some advanced features behind extensions, always. Perhaps we need to simplify the space of extensions (including a FancyTypes or DependentTypes extension), but I'd be happy to see these features guarded into perpetuity. About specification: The OutsideIn paper includes an overly-generous specification of GADTs, but not a precise one. I am unaware of a precise specification of what programs are accepted with GADTs, beyond the GHC implementation. Along similar lines, there is no specification of how type families reduce. (For example, what happens with `type family F where F = If True Int F`?)
How is a partial type signature a partially-written program? Does the absence of type signature on a binding make a program partially written? Because a partial type signature is more than no signature at all, so it should be considered less partial at least.
This is a good point. I see partial type signatures as a development tool, where a user elides part of a type signature in order to get the compiler to provide information on how to fill it in. But maybe that's not the best viewpoint. Richard

On Dec 9, 2020, at 6:17 AM, Spiwack, Arnaud
wrote: Or would you rather see these stay in their standalone extensions forever? (which I would find, personally, rather alarming)
I'm attacking from the standpoint that these will be extensions forever -- or, at least until we have a specification of them. (Amazingly, we don't have a specification for either one, right now.) Haskell will always have new learners, and I think it's reasonable to guard some advanced features behind extensions, always. Perhaps we need to simplify the space of extensions (including a FancyTypes or DependentTypes extension), but I'd be happy to see these features guarded into perpetuity.
About specification: The OutsideIn paper includes an overly-generous specification of GADTs, but not a precise one. I am unaware of a precise specification of what programs are accepted with GADTs, beyond the GHC implementation. Along similar lines, there is no specification of how type families reduce. (For example, what happens with `type family F where F = If True Int F`?)
This discussion is morphing into something bigger, which increasingly seems will be a subject for the year to come (as opposed to now). There appears to be a fairly strong divide on this subject.
How is a partial type signature a partially-written program? Does the absence of type signature on a binding make a program partially written? Because a partial type signature is more than no signature at all, so it should be considered less partial at least.
This is a good point. I see partial type signatures as a development tool, where a user elides part of a type signature in order to get the compiler to provide information on how to fill it in. But maybe that's not the best viewpoint.
I usually think that development tools are better handled with warnings. That being said, if what we are looking at is elaboration, then probably errors make sense (just like type holes make sense), though warnings work quite well too. But if we are looking at “I’ll do this later” then warnings are the only solution. Plus, there is a third usage of partial type signatures which are: I really want to specify part of this type signature, for this is where the information is (and maybe the rest is long and would distract from the point). This latter part I use frequently in type applications, for instance, where it is always allowed. Maybe one of the difficulties about partial type signatures is that it is not clear how to separate these three aspects. But I still think that PartialTypeSignature is perfectly serviceable. And could be improved by tuning the warning more as per this issue I once wrote and never got around to implement.
:set -XPartialTypeSignatures f :: _ -> _ ; f = (+) 1
<interactive>:3:6: warning: [-Wpartial-type-signatures] * Found type wildcard `_' standing for `Integer' * In the type `_ -> _' In the type signature: f :: _ -> _ <interactive>:3:11: warning: [-Wpartial-type-signatures] * Found type wildcard `_' standing for `Integer' * In the type `_ -> _' In the type signature: f :: _ -> _

On Wed, 9 Dec 2020 at 18:48, Richard Eisenberg
On Dec 9, 2020, at 6:17 AM, Spiwack, Arnaud
wrote: Or would you rather see these stay in their standalone extensions forever? (which I would find, personally, rather alarming) I'm attacking from the standpoint that these will be extensions forever -- or, at least until we have a specification of them. (Amazingly, we don't have a specification for either one, right now.) Haskell will always have new learners, and I think it's reasonable to guard some advanced features behind extensions, always. Perhaps we need to simplify the space of extensions (including a FancyTypes or DependentTypes extension), but I'd be happy to see these features guarded into perpetuity.
So let me separate the two points here: - Extensions without a specification shouldn't be part of the default language. I'd agree that they certainly shouldn't be part of the Haskell *standard*, but the bar for a GHC extension, even one that is enabled by default, is lower than this I think. (Indeed, one might point out that there wasn't a proper specification of the Haskell type system when the standard was published) - Whether advanced features like TypeFamilies and GADTs should need to be explicitly enabled. I disagree with this: 1. To a large degree these features already *are* guarded in the sense that you have to explicitly define a type family or a GADT. Having to jump through the extra hoop of adding a LANGUAGE pragma is unnecessary friction. Yes there are exceptions to this - needing a LANGUAGE pragma to pattern-match on a GADT for example - I also think this is unnecessary friction, because you can understand what the pattern-match does by looking at the definition of the type. Incidentally you don't need {-# LANGUAGE TypeFamilies #-} to use a type family in a type, so we're not very consistent here. 2. I don't think the extra signal of a LANGUAGE pragma or a flag in the Cabal file really adds anything useful for extensions that are largely stable. As a user you don't go looking for these things when reading code so that you can understand what dialect the code is written in, we just read code. There needs to be a common dialect as far as possible. Having said all this, there definitely *are* cases where you might want to *disable *fancy type features. At FB we have a large codebase of DSL code that is used by engineers with a wide range of Haskell experience, so we want to keep the level of fancy-types to a minimum. This is like the "beginner Haskell" use case where we want to be able to turn off a lot of advanced features to flatten the learning curve. This is an important use case that GHC should continue to support by having a way to turn off extensions, but I don't think it means that the default mode should also have these extensions disabled. Cheers Simon
About specification: The OutsideIn paper includes an overly-generous specification of GADTs, but not a precise one. I am unaware of a precise specification of what programs are accepted with GADTs, beyond the GHC implementation. Along similar lines, there is no specification of how type families reduce. (For example, what happens with `type family F where F = If True Int F`?)
How is a partial type signature a partially-written program? Does the absence of type signature on a binding make a program partially written? Because a partial type signature is more than no signature at all, so it should be considered less partial at least.
This is a good point. I see partial type signatures as a development tool, where a user elides part of a type signature in order to get the compiler to provide information on how to fill it in. But maybe that's not the best viewpoint.
Richard _______________________________________________ ghc-steering-committee mailing list ghc-steering-committee@haskell.org https://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-steering-committee

On Mon, Dec 7, 2020, at 22:47, Richard Eisenberg wrote:
A plea for NamedWildCards: This feature allows type variables beginning with an underscore to be treated as a component in a partial type signature. Critically (for this plea), a type signature with a named wild card will not be accepted without -XPartialTypeSignatures. I do *not* advocate for -XPartialTypeSignatures! So, having -XNamedWildCards on simply means that we get an informative error message when the user writes a type variable beginning with an underscore. The only downside is that programs such as id :: _a -> _a are no longer accepted. But does anyone write type variables with leading underscores? If we think this is at all common, then I would change my mind here. Why have it on by default? Because it's not easily discoverable, and the error messages really are quite nice.
Aha, so what you're saying is that with NamedWildCards but not PartialTypeSignatures, GHC will tell you what `_a` was solved for, but it won't accept the resulting program? I didn't realize that NamedWildCards did anything in the absence of PartialTypeSignatures, but I agree that this is better. I was already voting for NamedWildCards, but now I'm inclined to additionally vote against PartialTypeSignatures.

Hello,
On Mon, Dec 7, 2020 at 7:47 PM Richard Eisenberg
A plea for DerivingStrategies: GHC currently chooses which strategy to use rather arbitrarily. (For example, did you know that Eq and Ord are derived by GeneralizedNewtypeDeriving whenever possible, even when that extension isn't enabled?) And Show is always derived by the `stock` strategy, even when GND is enabled (and otherwise possible). Instead, DerivingStrategies allows users to be explicit, and (in my opinion) should be a matter of good style, just like top-level type signatures. Having to enable the extension to use good style is an annoying hurdle. While the set of strategies may evolve, the idea of writing out strategies (and their syntax) feels stable to me.
I agree that this is a problem, but instead of turning on more extensions by default, I think we should simply not turn on the GND by default. I really think that design for `deriving` is not quite at the state where it should be on by default. A plea for NamedWildCards: This feature allows type variables beginning
with an underscore to be treated as a component in a partial type signature. Critically (for this plea), a type signature with a named wild card will not be accepted without -XPartialTypeSignatures. I do *not* advocate for -XPartialTypeSignatures! So, having -XNamedWildCards on simply means that we get an informative error message when the user writes a type variable beginning with an underscore. The only downside is that programs such as id :: _a -> _a are no longer accepted. But does anyone write type variables with leading underscores? If we think this is at all common, then I would change my mind here. Why have it on by default? Because it's not easily discoverable, and the error messages really are quite nice.
It seems odd to turn on an extension that doesn't do anything, and it is entirely there to make *another* extension work better? Wouldn't it be better to make `PartialTypeSignatures` imply `NamedWildCards`? A plea against MonoLocalBinds (and, hence, TypeFamilies): MonoLocalBinds is
fork-like: it will mean that some Haskell98 programs will not be accepted. And to get those programs accepted, a user might need ScopedTypeVariables -- in specific, the aspect of ScopedTypeVariables that seems likeliest to change in the future. So I don't think we should have MonoLocalBinds on by default.
I think you are right on this, so I'll update my vote (I also don't think that `TypeFamilies` should be on by default, as I mentioned in my other e-mail) -Iavor
participants (6)
-
Eric Seidel
-
Iavor Diatchki
-
Joachim Breitner
-
Richard Eisenberg
-
Simon Marlow
-
Spiwack, Arnaud