Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Control what sort of entity a deprecated pragma applies to #167

Closed
wants to merge 17 commits into from

Conversation

nineonine
Copy link

@nineonine nineonine commented Sep 11, 2018

This proposal would allow to specify which entity (type or data constructor) you want to deprecate.

rendered
gitlab issue

@osa1
Copy link
Contributor

osa1 commented Sep 11, 2018

I think data is better than constructor for the reason mentioned in the proposal, and it's also shorter.

Not against this proposal, but I'm wondering if we could reuse haddock syntax for this. For example, in Haddock syntax we can annotate constructor or the type without ambiguity:

-- | Type documentation
data Foo =
    -- | Constructor documentation
    Foo x

so why not something like

-- | DEPRECATE: This type is deprecated
data Foo =
    -- | DEPRECATE: This constructor is deprecated
    Foo x

Perhaps as a solution to this problem we can ask people to use haddock syntax, and then deprecate the {-# DEPRECATED ... #-} syntax.

Just an idea.

@simonpj
Copy link
Contributor

simonpj commented Sep 11, 2018

I note that a module deprecation is positional. One says (I think)

module M {-# DEPRECATED "blah" #-} where ...

One could do the same for data constructors, thus

data Baz = Baz {-# DEPRECATED "blah" #-}
               | Boo
               | Bim {-# DEPRECATED "blah" #-}
                        Int

or in GADT syntax

data Baz where
   Baz :: Int -> Baz
   Boo :: Baz
   Bim :: Baz
   {-# DEPRECATED Bim, Baz "blah" #-}

This positional story works well when the deprecation is attached to the definition of the thing. If you want to import something, deprecate it, and re-export it, it would not work so well. But (I think) we can't do that anyway today.

@RyanGlScott
Copy link
Contributor

After reading this proposal, it seems like this is limited in scope to disambiguating prefix type constructors from prefix data constructors. But what about the following scenario?

module A where

type a <+> b = ...

(<+>) :: Int -> Int -> Int
a <+> b = ...

{-# DEPRECATED (<+>) "Don't use (<+>)" #-}

It's unclear which (<+>) I'm referring to, so I want to pick the value-level (<+>) in particular. But how do I say so with this proposal? Certainly not with the type specifier. That would suggest that data is the specifier to use, but that also feels a little awkward, since (<+>) isn't a data constructor.

The reason I'm picking this nit is because there is a separate, previously accepted proposal (Require namespacing fixity declarations for type names and WARNING/DEPRECATED pragmas) that also adds specifiers in a similar fashion to this proposal. However, it proposes adding specifiers named type and value (instead of type and data), since value is a more inclusive description that can apply to more entities than data.

Sorry for continuing to bikeshed about this name even more, but at the very least I'd like this proposal to be consistent with the other proposal (even if we end up changing the other proposal to use data over value).

@nineonine
Copy link
Author

nineonine commented Sep 14, 2018

Thank you for all your comments!
@RyanGlScott this is a great example! value keyword specifier definitely sounds more inclusive than data. I tried to think about an edge case where we would need to distinguish between data constructor and a function (with something like PatternSynonyms perhaps) but wasn't able to come up with example - it looks like it is restricted at syntax level so it is probably safe to have 1 disambiguating specifier for both these namespaces. Unless someone has something else in mind, I am going to update the proposal accordingly.

@nineonine
Copy link
Author

pinging @nomeata - I think this is ready to be reviewed.

@nomeata
Copy link
Contributor

nomeata commented Sep 30, 2018

Sorry for the delay, ICFP…

Before brining this before the committee, I’d like to raise one point: We already added a way to distinguish between the type constructor and the data constructor in export lists, and the ExplicitNamespaces language extensions uses type and pattern (also see the section on PatternSynonyms.

While it is a bit strange to call a data constructor pattern, I believe we should be consistent here.

In fact, I would be open to just extending ExplicitNamspaces with this feature, rather than adding a new language extension here.

When specifying several entities in one pragma, the sort of deprecated entity we've specified will apply to all listed entities. This will work - warn when these types are used(but not their constructors):

What is the rationale for this? I would expect that type Foo, Bar is the same as Bar, type Foo. Also, again the similarity to export lists calls for this.

@nineonine
Copy link
Author

@nomeata thanks for the comments.

I do agree that pattern looks somewhat strange in that case. But as long as everyone agrees on it, I will gladly change it.

When specifying several entities in one pragma, the sort of deprecated entity we've specified will apply to all listed entities. This will work - warn when these types are used(but not their constructors):

This is coming from the implementation that I already have in mind. I just added that bit to the proposal trying to cover all the possible corner cases. Frankly speaking, I am not sure whether this feature is even widely used (specifying several entities in one pragma). So this is just an implementation side-effect, so to speak, which I included in the proposal for the sake of completeness.

@nomeata
Copy link
Contributor

nomeata commented Oct 3, 2018

So this is just an implementation side-effect…

Even if that was the easiest way to implement it, and may few people use this feature, we should still strive for consistency with the rest of the language. And if in export lists (where we already have such qualifiers) they bind more tightly than commas, then I think they should do that here as well.

@nineonine
Copy link
Author

we should still strive for consistency with the rest of the language

@nomeata for sure, this is a good point and I wholeheartedly agree!
Updating the proposal accordingly.

@bravit bravit removed the Proposal label Dec 3, 2018
@bgamari
Copy link
Contributor

bgamari commented Jan 21, 2019

What is the status of this?

@nineonine
Copy link
Author

@bgamari proposal is updated according to the comments. I guess it is waiting to be reviewed by the committee ..

@bgamari bgamari added the Pending committee review The committee needs to evaluate the proposal and make a decision label Jan 21, 2019
@bgamari
Copy link
Contributor

bgamari commented Jan 21, 2019

Cool, @nomeata, it sounds like this needs a shepard.

@bravit
Copy link
Contributor

bravit commented Jan 22, 2019

@nineonine, could you please mention the idea of positional DEPRECATED pragmas as described here by Simon in the list of alternatives?

@bravit
Copy link
Contributor

bravit commented Jan 22, 2019

Before I am ready to make a recommendation, are there any thoughts (pro or contra) about moving to positional DEPRECATED pragmas instead? In fact, I think that this approach is better as it enables more fine-grained control over deprecated entities and we don't have to use pattern and other words. By the way, what about deprecating instances (see also this feature request and this note on deprecation mechanisms)?

@nineonine
Copy link
Author

Added positional deprecation idea.
I think this idea would work equally well and I cannot think of any bad consequences of going that way right now.
Deprecating class instances sounds like a great idea too, I added this to "unresolved questions". I wonder what others think about that..

@bravit
Copy link
Contributor

bravit commented Jan 26, 2019

@nineonine will you be able to rewrite/reimplement the proposal if the Committee decides in favor of positional pragmas?

@nineonine
Copy link
Author

@bravit sounds good.

@simonpj
Copy link
Contributor

simonpj commented Mar 8, 2019

Hang on. No one has addressed Ryan's point, where he points to the already accepted proposal about namespacing for infix and WARNING pragmas.

Isn't namespacing for DEPRECATED pragmas precisely the same problem? Can't we simply adopt precisely the same solution?

We don't want to add inconsistent solutions!

Arguably, if we like value in the infix/WARNING proposal, we might want to shift from pattern to value in export lists for pattern synonyms.

@bravit
Copy link
Contributor

bravit commented Mar 8, 2019

@simonpj, in fact, it was addressed. We have three options here: to choose either "data", "value", or "pattern". Richard Eisenberg wrote on the committee's mailing list:

Though I understand the reasons against it, I'm an unabashed supporter of using the word "data" to supplant "pattern". My principal argument is that data can be used freely in the syntax, given that it's a keyword that has current meaning only as the first lexeme in a top-level declaration. (Specifically, I pine for a future where types and terms mix. We can then use type and data in the middle of expressions/types to denote namespaces.) It also works nicely to mean "data constructor". I agree that it doesn't work as well with functions or the potential confusion around "data Bool = True | False" (though, in that last example, we can pretend hard that the data applies only to the bits after the =). The problem with value is that we would have {-# DEPRECATED value, foo #-} mean something very different than {-# DEPRECATED value foo #-}. This isn't a deal-breaker (punctuation normally is important in programming), but it's unfortunate.

The same argument applies to infix/WARNING proposal, so I think that we could change it either (anyway, it is not implemented yet afaik). I personally prefer "data" over "value", and "value" over "pattern", but I'm not ready to die for that.

@simonpj
Copy link
Contributor

simonpj commented Mar 8, 2019

OK -- so at let's agree, at least, that whatever is decided here applies equally to the infix/WARNING proposal. And I would argue that it ought to apply equally to export and import lists, though that would need a careful migration path.

OK, so do we really want to write

infix 3 pattern `foo`

{-# DEPRECATED pattern foo "Do not use foo" #-}
foo :: Int -> Int -> Int
foo  x y = y - x

Obviously foo isn't a pattern!

And data would be pretty strange there too.

Personally I'm fine with value. It's true that

infixl 3 value value

would be pretty strange. But I don't expect it to happen in 99.999% of programs, and I care about the 99% case a lot.

@nineonine
Copy link
Author

Updated the proposal to use value for value level things.

@nineonine
Copy link
Author

I was thinking today about the implementation and it led me to the following question - what do we want to happen when wrong specifier was used?

{-# DEPRECATED type ack "blah" #-}
ack = ()

Currently I see 3 options:

  • warn user about misused disambiguator and ignore malformed deprecation
  • ignore disambiguator and treat it as unqualified case
  • completely ignore deprecation and do nothing

@nomeata
Copy link
Contributor

nomeata commented Mar 19, 2019

@nineonine did you see #214? That is a more ambitious attempt to fix all that, which likely subsumes this proposal. Please comment there as well, if you find it lacking (or to voice your support)!

@nineonine
Copy link
Author

nineonine commented Mar 19, 2019

@nomeata no I didn't! thanks. Although, I am a bit confused now. What is the destiny of this proposal/thread and ticket 3427?

@bravit
Copy link
Contributor

bravit commented Mar 20, 2019

@nineonine it turned out that the proposal on namespacing in the DEPRECATED pragma (among other things) was already accepted more than a year ago. That's why there is no sense in accepting this proposal now. That proposal and your proposal are now subsumed by #214. Hopefully, it will be accepted and implemented once, that will close the ticket you mentioned.

@nomeata nomeata added Rejected The committee has decided to reject the proposal and removed Pending committee review The committee needs to evaluate the proposal and make a decision labels Mar 20, 2019
@nomeata
Copy link
Contributor

nomeata commented Mar 20, 2019

Right, as @bravit said: Your proposal pointed out the need for a larger reorganization around namespaces, and as such it was very helpful, thanks for that! I hope that once #214 or something similar is accepted, your itch will be sufficiently scratched as well.

@nomeata nomeata closed this Mar 20, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Rejected The committee has decided to reject the proposal
Development

Successfully merging this pull request may close these issues.

None yet

8 participants