-
Notifications
You must be signed in to change notification settings - Fork 330
Documenting expected behaviour of intersection types #13384
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
base: develop
Are you sure you want to change the base?
Conversation
- inspecting the type via `case of`, e.g. | ||
``` | ||
case x of | ||
a : A -> ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens in this case?
a : A -> ... | |
b : B -> ... | |
a : A -> ... |
``` | ||
in the first branch, the `a` has visible type `A` but the full type is still | ||
`a : A & (hidden B)` - the `B` part is hidden, but not removed. | ||
- dispatching a method on one of the types, e.g. calling `x.method_defined_on_A` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it the same when calling a method defined on a hidden type? x.method_defined_on_B
?
will pass the value `x` as `self` to the body of `method_defined_on_A`, the | ||
`self` will have a visible type `A`, but the full type is still | ||
`self : A & (hidden B)` - so the `self` value can be casted if needed. | ||
- normally, calling conversions will 'start over' and the value returned from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if there are conversions from both A
and B
to some other type? Do unhidden ones take precedence over hidden ones?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Thanks for improving the docs, Radek.
- I prefer positive tone in the docs
- e.g. describe how great Enso design is
- and only then warn what would happen if it wasn't as great
@@ -198,3 +248,10 @@ _has been cast to_. As a special case any value wrapped into an _intersection | |||
type_, but _cast down_ to the original type is `==` and has the same `hash` as | |||
the original value. E.g. `4.2 : Complex&Float : Float` is `==` and has the same | |||
`hash` as `4.2` (in spite it _can be cast to_ `Complex`). | |||
|
|||
### TODO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the purpose of this TODO? If the functionality is broken, can we link to the appropriate issues?
self preserves intersection types, just hides them
That works, doesn't it?
@@ -181,6 +181,56 @@ In short: when a [conversion](../syntax/conversions.md) is needed to satisfy a | |||
type check a new value is created to satisfy just the types requested in the | |||
check. | |||
|
|||
## Preserving identity of refined types | |||
|
|||
Intersection types are used to refine a value giving it additional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Intersection types are used to refine a value giving it additional | |
Intersection types are often used to refine a value with additional |
this compound type may get _hidden_ when passing around various methods (e.g. | ||
`table:Table` will hide the `DB_Table` part), but the value itself still retains | ||
its identity as a `Table & DB_Table` and can be uncovered via a cast or a case | ||
expression. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
expression. | |
expression during runtime. |
its identity as a `Table & DB_Table` and can be uncovered via a cast or a case | ||
expression. | ||
|
||
It is important to ensure that various operations do not accidentally remove a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I don't like the term various operations
- it only spreads FUD
- there is no point of being so vague in the documentation
- if you have to, move it into a "warning" or "notice" section
- e.g. a colloquial knowledge, not part of the spec
It is important to ensure that various operations do not accidentally remove a | ||
part of the intersection type as then the value completely loses its part of | ||
functionality. If the `DB_Table` part is not hidden, but completely removed, the | ||
table can no longer be casted to `DB_Table` and used as such. This is confusing | ||
for users, as a database table cannot suddenly stop being a database table just | ||
by passing it around (including method calls) or casting. | ||
|
||
Consider a multi value `x : A & B`. We indicate hidden types as `(hidden T)` - | ||
they are not visible in the actual type, but can be uncovered via casts or | ||
reflection. | ||
|
||
To ensure the above properties, the interpreter ensures that the following | ||
operations only hide the intersection type, but do not remove it: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is a short version:
It is important to ensure that various operations do not accidentally remove a | |
part of the intersection type as then the value completely loses its part of | |
functionality. If the `DB_Table` part is not hidden, but completely removed, the | |
table can no longer be casted to `DB_Table` and used as such. This is confusing | |
for users, as a database table cannot suddenly stop being a database table just | |
by passing it around (including method calls) or casting. | |
Consider a multi value `x : A & B`. We indicate hidden types as `(hidden T)` - | |
they are not visible in the actual type, but can be uncovered via casts or | |
reflection. | |
To ensure the above properties, the interpreter ensures that the following | |
operations only hide the intersection type, but do not remove it: | |
To ensure intersection types properly propagate thru the Enso program the | |
basic language constructs are designed to handle them properly. Namely: |
the actual wording can be different, but I'd prefer the positive focus rather than description of catharsis in the docs.
- similarly, calling `B.from x` will return a value of type `B & (hidden A)` - | ||
the `A` part is still there (only hidden), because no actual conversion code | ||
had to be run. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please note the use of these operations rather than various operations ;-)
It is important to ensure these operations do not remove a part of the intersection type. | |
Otherwise the value loses part of its functionality which would have a detrimental effect | |
in the GUI, confusing users. | |
If the `DB_Table` part is not kept as hidden, but completely removed, the | |
table can no longer be casted to `DB_Table` and used as such. |
A little Cassandra's warning at the end may be acceptable...
Pull Request Description
Important Notes
Checklist
Please ensure that the following checklist has been satisfied before submitting the PR:
Scala,
Java,
TypeScript,
and
Rust
style guides. In case you are using a language not listed above, follow the Rust style guide.
or the Snowflake database integration, a run of the Extra Tests has been scheduled.