-
Notifications
You must be signed in to change notification settings - Fork 53
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
Nominal typing #413
Comments
A message to ballerina-dev specifically highlights the case of wrapping an existing simple type. One design issue is to what extent to prioritize that compared to records. My sense is that approaching the problem as a something that is layered on records is going to be a better fit for the language as a whole and for JSON/GraphQL. |
The fundamental idea is integrating nominal types into a structural language by having some sort of named marker attached to values. I believe this is usually called brands or branded types in the literature. Modula-3 has a |
GraphQL |
It would be nice to be able to have a keyword that returned the org, module, and scope at compile-time, so that the "brand" wouldn't need to be maintained. In the C world this would be akin to the __ FILE __ and __ LINE __ macros, a bit like __ ORG __, __ MODULE __, and __ SCOPE __. __ FULLSCOPE __ might combine these three. That would give us this, which feels like an improvement since the record is self-contained.
|
My original suggestion was for using tuples to create simple distinct types. Essentially this allows the creation of a new "bottom" to a type hierarchy that is above the basic type. My hope was for a the basic type to be fully encapsulated and not easily accessible. I had envisioned the need to use casting to convert to/from the basic type (except for literals). I still think this is the cleanest approach and worthy of some thought for simple distinct types (a two element tuple -- one value and one constant.)
One option would be to allow the use of underscore on the RHS when destructuring a tuple, with the RHS underscore meaning "don't replace." For a tuple with constant elements this makes sense. Actually, for constants it wouldn't even be needed (see nickname assignment below).
Having said all that, I'll be happy with whatever approach makes sense for the community as a whole. |
Here is a paper outlining how the authors added nominal typing capability to a structurally typed language: https://michael.homer.nz/Publications/ECOOP2015/paper.pdf . |
If we had branded types we could use the brand of an error type as the default error reason value too. |
Flow has an interesting concept of opaque types. |
We've been using tags/brands to overcome similar issues in our Ballerina compiler codebase. |
@sameerajayasoma That's an important use case. Nominal typing design ought to provide a solution that is usable for this. |
There's now a proposal. |
James why do you say this:
Why can't I say error<readonly & record {| int x; |}> to create an error with a detail record that is not open? Why do we require error detail records to be open? |
It would get very confusing with |
Regarding the intersection of object types.
|
Conclusions from meeting:
|
@sameerajayasoma I added an issue on function intersection types #506. |
Additional changes still needed to the spec:
|
Semantics explained in commit 2baf5ae |
Introduce object:Iterator Part of #413.
Decided today not to require value:toString's use of toString on objects to require distinct type. |
Rework type inclusion section. Part of #413.
Ballerina is fundamentally a structurally-typed language, but there are cases where nominal typing would be useful, both for improved error checking and for interop with other systems that use nominal typing. Examples of the latter include SQL (with distinct types) and GraphQL (the __typename feature).
At the moment we can simulate nominal typing like this:
You can then say:
and the
_typeName
field gets defaulted.The planned functional constructor syntax combines nicely with this:
Private fields in objects also provide a way to create the effect of nominal typing. See #43 (comment)
This relates to a number of other things in the language:
_typeName
field is interesting in that it has a single possible value, and that value is immutable, which means the field is effectively immutable; there are a couple of other language features that also potentially have immutable fields (for table primary keys and event stream timestamps)The text was updated successfully, but these errors were encountered: