-
Notifications
You must be signed in to change notification settings - Fork 30
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
SIP-67 - Improve strictEquality feature for better compatibility with existing code bases #97
base: main
Are you sure you want to change the base?
SIP-67 - Improve strictEquality feature for better compatibility with existing code bases #97
Conversation
fix indentation
Thank you for the proposal. Here is the feedback from the SIP Committee:
|
Hey @soronpo, I'm sorry, I'm afraid I can't do that. Please consider the following enum:
I'm going to contend that it shouldn't ever be allowed to compare two
This is not a bug, this is a feature. Now you might say, OK, then maybe we can make the
Alas, while this does prevent nonsensical comparisons with
(insert sad trombone sound here) Now you might ask: How come it works just right for
That seems like the sweet spot! The reason this works is that The conclusion from all of this is that it's impossible to make this work correctly by providing a magic |
I would not consider this to be a valid use of enum. Have you seen this type of code in the wild? |
Not sure offhand, but it seems like it would be unsurprising when constructing a DSL interpreter. (Where the enum is a kind of expression, and the leaf is an instantiation of one expression type.) The interpreter for my own QL language is still on Scala 2, but I could see myself trying to build it along those lines if it was Scala 3, so I don't think that's just a strawman. |
Still I'm not sure |
I have seen ADTs with functions inside |
From the Scala 3 book.
Personally I have almost exclusively written Scala 3 and would use enums for this kind of ADT (with a function). If that is not the correct way to do it, then the correct way must be elusive. |
Yeah, agreed. My understanding of the Saying that only some ADTs count, and other reasonably well-formed ones don't seems kind of un-Scala to me. A key element of Scala is that functions are values; intuitively, I would expect them to work here like any other value type. |
I have to agree with @jducoeur , what's the actual argument against functions in The GADT mention is not accidental, the main use case for that is encoding commands: enum Cmd[A] {
case Read() extends Cmd[String]
case Write extends Cmd[Unit]
} and command-like GADTs will often have functions in them to allow sequencing: enum Cmd[A] {
case Read() extends Cmd[String]
case Write extends Cmd[Unit]
case FlatMap[O, A](fa: Cmd[O], f: O => Cmd[A]) extends Cmd[A]
} I feel like the argument that |
Let me clarify. If you want function arguments that should not be part of the pattern match, then these should come as a second argument block of the case, IMO. enum Cmd[A]:
case Read() extends Cmd[String]
case Write extends Cmd[Unit]
case FlatMap[O, A](fa: Cmd[O])(val f: O => Cmd[A]) extends Cmd[A] If you want them to be part of the pattern match, you put them in the first block where they have same equality treatment like all the other arguments. |
I admit that I never played with strict equality, so this might not make much sense, but:
Do we need a Now, from what I can tell based on some quick tests, the compiler really wants a |
Hi @JD557,
Yes, I had this in mind and I was going to propose it – you beat me to it. It can't be done with just a magic I. e.
Then all we would need is a magic |
First of all, I'd like to address the question of "in the wild" examples of functions within ADTs. This is definitely something that people do, e. g. I think this is perfectly good code. It should be possible to use |
I've pushed a new revision that is based on a minor change to |
@mberndt123 Hey Mathias, thank you again for the amendments. We discussed the SIP today and we strive for a more general approach: A case class or enum case will be considered to have |
Hi Oron, I have considered the committee's proposal and would like to present my conclusions.
What the committee's proposal does do is make
For all of these reasons, I think "fully automatic" typeclass derivation (i. e. typeclass derivation that works without an explicit To sum up: the committee's proposal doesn't solve the problem that the SIP is designed to solve. It doesn't make the Thinking about this issue once more made me realize that my own revised proposal has a safety problem. It mentions a "union or intersection of one or more ADT pattern matching and equality tests are separate things, and the fact that Scala has conflated them is a historical mistake. The best way to move forward now is to untangle them as far as possible: simply don't require a Regarding Best Regards |
…m pattern matching entirely
We had a SIP discussion, and we'll vote on it next time, but I was just thinking about it and the specification needs to account for any singleton that is a sub-type of the matched type, which unreachability already does check for.
I don't know what to think about the function type example now. |
Co-authored-by: Seth Tisue <[email protected]>
Hey @soronpo Yes, you're right, that code does not compile under the rules I've proposed: I also don't think that special-casing literals is a good solution here because it should always be possible to use a named constant instead of a literal with a minimum of fuss. IOW, if it works for the pattern It should also be pointed out that strings, unlike case objects and singleton enum cases, are not singletons. val a = "a" * 10
val b = "aa" * 5
a eq b // false
a == b // true So the philosophical reasoning described in the SIP does not apply to Strings. |
I agree with @mberndt123 that Any-comparisons are dubious and the whole point of strictEquality is making risky business not compile. However, I think it is very important to have good error messages so that a learner can understand why such a match don't compile. I'd like to see a future where structEquality is the default, but to get there we need to make it really ergonomic and error messages, docs and other help to the user/learner is critical to making that happen. After all, safety is next to scalability a unique selling-point of Scala and we should always prioritize sound and ergonomic language features that improve safety, IMHO. |
I think the point is for equality. Pattern matching does not fall under this category beyond reachability concerns, IMO. |
But |
For the record, strict equality is applied to |
Aha, thanks @soronpo for the clarification. Yes, nobody knows what |
@mberndt123 Perhaps update the proposal to upfront clarify the scope of being |
Pattern matching uses locally {
val x: Any = 5L
println(x == 5) // true
println(x.equals(5)) // false
println(x match { // yes
case 5 => "yes"
case _ => "nope"
})
} |
Hi Björn, What @soronpo wrote there is not a clarification, it is his opinion, and it is in fact exactly where the controversy is. Currently, pattern matching against a constant (whether it's a literal or a case object or just a |
AHA!! Thanks also to @mberndt123 and @sjrd for yet more clarifications. Maybe it's just me who didn't get the actual controversy, but perhaps the intro to the SIP can be improved by referring to I think I'm leaning towards the stricter end of the design space of the future language - it is after all called strict equality. |
What I meant is that I think it should be equals and therefore not affected by strict equality |
It has had the semantics of IMO we should judge the present SIP with respect to the established semantics of pattern matching. |
I'm ok with keeping == and just inferring CanEqual under pattern matching, as I have already mentioned. |
Hi there,
I'd like to use the
strictEquality
feature for the improved type safety it provides, but currently find it too inconvenient to use due to an unfortunate interaction with pattern matching. This SIP is my attempt to fix that.There have been no comments in the Pre-SIP thread for the past two weeks, and it's a very small (though impactful) change to the language, so I felt it was time to submit it.
Best regards
Matthias