Conversation
36cda5d to
fe82e1a
Compare
|
I like the general gist of this proposal. I will have to mull it over for some time to see if I like the details. A few isolated thoughts:
Thanks for writing this up! |
You're right that's an implementation detail. I've updated the proposal so the specification no longer depends on it.
No, you can, and I don't really understand why would that be useful. Perhaps I'm missing something? Consider this scenario: In this case, only
Sorry, I forgot to specify this,
Good point! Perhaps
Indeed! I've clarified this in the proposal.
Good point, I've moved that part to specification section. |
|
This is a big change. I think we should be very careful to be sure we get exactly what we want in the end. Personally, I don't see the need to get rid of A minor thought: if we have to monkey around with tuples, should we make them a built-in data family? data family Tuple (ts :: [Type])
data instance Tuple [] = ()
data instance Tuple [a] = Solo a
data instance Tuple [a,b] = (a, b)That way we won't need to import a tuple module to get a bunch of numbered tuple names. |
|
I'm not at all convinced by this. The motivation as stated is three points:
|
It is a localized change. The code that doesn't use
We're only getting rid of
That code is unaffected, you only have to worry about it if you have
It's forced by the fact that we need to refer to types on term level and to terms on type level. You can see another example below (I've also added it to the proposal).
That is a nice suggestion! Unfortunately, you can't partially apply -- You can do this with Tuple2
F (Tuple2 a)
-- but not with Tuple
F (Tuple [a, ?])
F (\b -> Tuple [a,b])
It is true that newcomer confusion is mentioned in both motivation and drawbacks, but I believe the introduction of the new
What should be the meaning of
We do have a Richard Eisengberg's paper Dependent Types in Haskell: Theory and Practice which pretty much describes the end goal that we're currently moving towards. This is also be useful in cases other than Dependent Haskell, for example with visible dependent quantification. Here's a closer to the real world example with sizeOf :: Storable a => a -> Int
-- To use it we have to do this:
sizeOf (undefined :: MyType)Here's an example of hasktorch using this pattern. With sizeOf :: forall a -> Storable a => Int
sizeOf MyTypeOf course, there's an option to use sizeOf :: forall a. Storable a => Int
sizeOf @MyTypeBut the problem here is that the argument here is not required and if you forget to put it there GHC will try to infer it which will lead to errors like "could not deduce" which do not directly hint to what the problem is and how to fix it. I've updated the proposal with this example. Furthermore, other dependently typed languages like Agda and Idris use pretty much this approach: they have a single namespace for everything. |
|
Well, there has been no comments in a while, so I guess it's time to submit! @nomeata |
|
Since most modules define both types and data, wouldn't this extension double the number of imports required? I mean this for the imports that are explicitly annotated with a namespace. Also, it seems that this extension is conflicting with itself---to define the module that renames the types, you'd have to turn off this extension correct? I am extremely unconvinced by the motivation:
So, overall, I am not convinced that we'd be gaining much here, and the cost seems quite high. Am I missing something? |
Yes, although such imports would be needed only for disambiguation purposes. For example,
That module would be a compatibility shim. Of course it'd be nice to live in a world where we're dealing with
Indeed, it is crucial to understand the difference between
I believe this one is a no brainer for anyone who actually tried to explain Haskell to beginners.
Dependently typed programming implies the use of types and terms together, we already can refer to the term namespace in types with
And this proposal offers an alternative way that data promotion could work, a way that doesn't require promotion quote syntax. Hence, accepting this proposal means we get rid of the aforementioned wart.
What makes this change "big", how do you quantify its size? It doesn't break any code whatsoever because it's opt-in, and modules that don't enable the extension can seamlessly use the modules that do. Therefore, for users who opt-in, the impact of this proposal (big or not) is desired, and for users who don't opt-in, the impact is zero. As to the gain of this proposal, it is quite clear to me that the gain is immense, as it solves one of the fundamental challenges towards dependently typed programming in Haskell – the namespace problem.
It is not enough to say that there are alternative designs, one must name them. So far, I can name three:
It is quite related to both Dependent Haskell and namespaces. The landmark feature of Dependent Haskell is the As soon as we're dealing with visible arguments, by definition we're not using the visibility override
This makes the assumption that we make a distinction between terms and types, whereas the entire premise of this proposal is that we're moving towards a future where we do not make such a distinction. Types are values of type
Hopefully, I was able to clear a few things up. The proposal has close to zero costs, as it's entirely opt-in and has no impact on non-users. Its implementation is not difficult either. It is of huge importance for the dependently-typed programming movement as it resolves the namespace problem. |
|
How do exports from a |
|
Entities defined in a module with Now both |
|
Great, though I think the proposal should call that out explicitly? I agree that that this proposal
I don't see who gets hurt in this scenario. |
@Hithroc Would you mind extending the proposal to make this more clear?
The user code that uses the extension:
I do share the feeling that this is not a small change because it would lead to very different naming conventions. Haskellers (including myself) are very used to punning, but now instead of writing Of course it's not a small syntactic change like, say, #87 or #190, but it's not exactly heavyweight either? |
|
@int-index Sorry! I meant it does seem lightweight. I had "doesn't seem heavyweight" before or something 😂 |
|
Hehe in terms of ecosystem effects, I wouldn't say it's like GPL vs MIT; both multiple namespaces and unified namespace work better when all the other code uses the same scheme, so unified namespace will have the worse hand for a while. |
|
Oh, and regular namespaces should have some way to get the additional import syntax, so they can "confine" a unified namespace module's exports to one namespace too. That should give the old-style modules maximal flexibility for dealing with the new style |
|
Let me just note that this proposal introduces a "fork" in the language, in the sense decribed by Simon Marlow in his email earlier this month. He says A "fork" is the thing I think we should strive to avoid. What is a fork?
Unlike, say, That leaves the second test. We might conclude that this is the right direction of travel, and I can see its advantages. But I doubt we are ready to say "yes, this is what future Haskell will be like, and we'll be deprecating the two-namespace version in due course". That's not to say that we should never accept a fork-like proposal -- there are judgements everywhere. But an alternative would to park this one until the need becomes more proximate; that is, until we want accept a dependent Haskell proposal that really needs it. |
Visible I'm counting on either this proposal or an alternative to solve this issue before I (or a collaborator) formally propose visible I encouraged @Hithroc to make a separate proposal for this namespace problem, but it could also be bundled with the visible |
|
Maybe we can have both proposals up at once, with the dependency made clear? I think the connection is simple enough that it shouldn't feel like a split conversation. |
|
@yav:
My experience with teaching Haskell suggests that different names for types and terms would be a net benefit. It's certainly not a primary challenge in teaching Haskell, but I've found it to be consistent. Others' experiences may differ, and I have no real data to offer on the matter.
That would be a separate proposal, but it depends on either this one or some other solution to the namespace problem. If I
That discussion has points on both sides of this issue. I think it's helpful background, but I don't find the discussion moves the needle here much.
I think it's fair to say that everyone has their own experiences here. My experience agrees with yours.
In other words, this proposal or something similar is a necessary prerequisite for dependent types, in my opinion.
I disagree fairly strongly here. All users are affected, because libraries will start to program in this new style. Everyone will eventually have to be aware of this extension.
If I wasn't clear on this point before, I would like to amplify the sentence above. This really is of huge importance to dependent types, and I don't have a better solution than this one.
I agree. And that is worrisome. I'll also explicitly agree with Simon's text, that this extension is not for everyone today, but could conceivably work its way into a future standard. An interesting counterpart to forking is #214, which does not fork the language, but is otherwise quite unsatisfying. I honestly don't know what's best here.
I think this is a fine idea. I personally wouldn't bundle this with the visible-dependent-quantification-in-terms proposal, but we could usefully debate both at the same time. |
@yav seems to be suggesting that we use
Though presumably this would also imply part of a solution to the namespace problem, that solution probably being something like Personally I like the unified namespace approach more for all the reasons that have already been brought up in this discussion, and also because being able to call both edit: I just realized, it might be worth mentioning how this will interact with the accepted but (as far as I can tell) not yet implemented #65. |
@simonpj and I briefly discussed this proposal elsewhere, and if I understood correctly, the fork-like nature of this proposal is the biggest obstacle to its acceptance. A possible alternative is to make punning a warning instead of an error. That is: In fact, adding this warning would not even need a proposal, as it's not a new language extension. And the users could make punning an error using the existing Whether to enable this warning and whether to make it an error is a matter of style rather than language design. And the part of this proposal about ambiguity and teaching beginners can be addressed with the warning, so with that out of the way, we are free to discuss what we actually need for visible Surprisingly, the part that's needed for
We could extend these rules to:
This would mean that the following program would work fine: There are no data constructors In this case, GHC would select the term-level
So, while there are disadvantages, they can be addressed. As to the advantages:
I would prefer to see the proposal accepted in its current form (punning as an error), but it's true that this would have the (possibly unwanted) implication that we are moving away from punning:
On the other hand, punning as a warning is unopinionated and does not have such implications. And it would unblock visible |
|
I'm opposed to using I like the idea of Separately, we could still retain the Actually, there's a wonderful balance here. I offer this counter-proposal:
Those points should address the needs in this ticket and be scalable to dependent types (and fairly ergonomic in the future). This counter-proposal is not fork-like! I would actually like to go further, adopting some of my thoughts from #214:
This "further" could reasonably be a separate proposal, but life is short. What do we think? |
|
I do support the proposal, but I am also not happy about forking the language. So this is most likely a unpopular opinion, but I would suggest to add a deprecation plan for punning with a long overall timespan, similar how EDIT: This also means that the Prelude and |
|
As a committee member with sometimes a short memory, I'm surprised by the last comment here. Why was this rejected? There are a bunch of comments above that sound like "here's just a few more cleanup things we need before merging", after which a rejection seems quite dispiriting. In any case, there hasn't been visible action here over the past week -- I do hope this hasn't started withering! |
|
Chris asked me how do I feel about removing the part about However, I had to disagree that this is the way to go. This proposal does not make sense without the changes to |
|
I argued against acceptance of the proposal as-is on the basis laid out here: https://mail.haskell.org/pipermail/ghc-steering-committee/2022-December/003059.html. My main concerns are about the changes to @Hithroc to be clear, I'm very grateful for all your work on this, and I hope to see this proposal accepted in some form. I'm sorry that this process can be drawn out and difficult, and hope this doesn't feel too demotivating. Language specification is a tricky task!
Splitting out the extension changes into a separate proposal seems like a good idea to me, as it will allow quicker progress on the warning parts, and more space to focus on the extension changes explicitly. Given that these warnings will not be enabled by default, I don't see it as a big problem to have one proposal that introduces them (even if some warnings cannot be avoided when importing a punned type) and then a follow-up proposal that is motivated by allowing the warnings to be avoided. I would be happy to help with drafting such a split if that would be useful? That said, if you prefer to keep everything together in a single proposal and incorporate detailed motivation, specification and examples for the changes to extensions, I don't think a split is essential. |
|
An alternative to splitting the proposal would be, to me, to introduce a new Then I think this proposal can stay as one. |
|
I agree with @nomeata. A topic that came up at work recently was bundling, in that it can be easy to think that two objectives/tasks/goals/whatever are required to be addressed together, when really they are separable. I fear there has been some unnecessary bundling here, where we've somehow decided that the specification of an existing Once we make a new extension here, then I see no remaining blockers. And then it would be great to clean up |
|
I personally think using a different extension name would be no bad thing, though I am aware there are differing opinions about how much change to existing extensions is warranted, so I wouldn't consider it a blocker either way. The point is that, regardless of whether we are changing existing extensions or introducing new ones, those changes need to be clearly specified! 😄 |
|
I agree with @adamgundry whose analysis of the issues here has been outstanding. I am very busy with other business right now but (as I told @Hithroc) I have scheduled the start of Feb (w/b 2023-02-06) to return to this. |
|
Decoupling the changes to imports in this proposal from
|
True. But not necessarily better than one extension meaning widely different things in different versions of GHC, and also not necessarily better than tying this change to an extension that some expect to be redone in the future. Especially if one sees extensions as merely a stepping stone towards a future language edition where the new feature is simply part of the language, then having one more is only a temporary nuisance for early adopters, and can also help form the future language more selectively (e.g. include the present change, but a revised ExplicitNamespaces variant). |
|
I'm working with @Hithroc and @cdornan on a new proposal text, essentially derived from this one and the previous work in this area, that will tidy up I think ultimately the question of one extension or two isn't very important, because I don't think we should use "let's add a new extension" as a way to avoid nailing down the interaction with |
|
As @adamgundry said, we have a proposal in the works — it will aims to fix |
|
For reference, the new proposal for the @Hithroc Now that it's out, how would you feel about amending the present proposal to focus on the new warnings? (I'm happy to help if you'd like, but you're the proposer of this one so I wanted to give you the option first!) |
|
Thanks @adamgundry! |
|
@Hithroc clearly there is not a rush on this — hopefully this is all moving forward again. |
|
Awesome. I'll get the proposal updated over the weekend. |
|
@Hithroc Just a quick checkin — are you still OK to make these revisions? |
|
Am I allowed to ask a quick q here? I'm puzzled by 3.2.6 -Wpun-bindings, example #1, second part:
(Not what I'd call "fine".) If I try to make use of the That'll actually use the (Asking because the consequences of the consequences of #608 are getting tangled.) Edit: perhaps a more critical illustration |
|
Thanks @Hithroc for your work on this proposal. I'm unassigning it as sadly @cdornan is no longer with us. It appears that previous discussion on this proposal petered out, so I'll mark it as dormant. The main thing it needs is revision as described in #270 (comment), and there's a recent open question in #270 (comment). If anyone would like to pick this up, please feel free to shout. |
This proposal introduces
-Wpunsand-Wpun-bindingsandintroduces namespace-qualified imports and module aliases.
These changes should help the users to write pun-free code to take advantage of
Syntactic Unification Principle described in #378.
Rendered