-
Notifications
You must be signed in to change notification settings - Fork 259
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
Restore late-binding for constraints within typealiases #510
Conversation
This fixes an issue where a constraint within a typealias is not late-bound.
Late-bound typealiases are useful, but they also make for harder to understand code (you can't just follow the typealias to understand the type). |
I've been thinking about equality of types (and especially of
This is an imperfect equality operator, but it's an understandable concession to the fact that you can't generally decide functional equality. There are easy intuitions to this, because it only has false negatives (as in The problem with late-bound constraints in I've been thinking; what if we can keep Lets define
However, since we already know our operands have the same definition, they're structurally equal (so
This does require that sometimes Very concretely, in terms of your example, I'm proposing the following evaluation:
and even if we change
we get
However, if we also remove the overwrite of
The cost of this equality operation grows linearly with number of late-bound members in the type constraint of the ... and for folks who rely on the current locational equality of |
And, for context, a few observations about lambda equality currently:
|
I agree that we can find a way to get around the equality problem. Although, I don't think that's actually the problem with this proposal. This proposal still seems like strange behavior to me because you can change a typealias's behavior and identity by amending the module. We enforce that schemas cannot be changed by amending (hence, why a class body can only reference Let's consider classes. This seems like obviously a bad thing: // module1.pkl
name = "Bob"
class Person {
name: String(startsWith(module.name))
} // module2.pkl
amends "module1.pkl"
name = "Sarah" import "module1.pkl"
import "module2.pkl"
person1: module1.Person = new { name = "Bobby" } // okay
person2: module2.Person = new { name = "Bobby" } // fail; name needs to start with "Sarah" This would mean that the meaning of a class can be changed by amending its enclosing module, and this is a behavior that we do not want (classes should be statically defined). Given the above, I feel that typealiases would break this principle in the same way. // module1.pkl
name = "Bob"
typealias PersonName = String(startsWith(name)) // module2.pkl
amends "module1.pkl"
name = "Sarah" import "module1.pkl"
import "module2.pkl"
person1: module1.PersonName = "Bobby" // okay
person2: module2.PersonName = "Bobby" // fail; name needs to start with "Sarah" I don't know how this is any different than the problem we see with classes. The alternative proposal here is: references from a typealias body must be |
Closing this; I believe this approach presents more problems than it solves; more details can be found here: https://github.com/apple/pkl-evolution/blob/1707776862c12d10fc57f4d38a3b3610793a2bc5/spices/SPICE-0007-const-checks-in-typealiases.adoc#alternatives-considered |
This is one proposal to fix #446.
This changes the behavior of typealiases such that:
This implies that the meaning of a typealias can change depending on where it is resolved from. Given the following:
These two properties have different type checks:
Despite this, they are considered the same typealias.
This is somewhat quirky. An alternative solution to this problem is to require any references from a constraint to be
const
. This is just like how classes work. However, this solution would limit the usefulness of typealiases.