-
Notifications
You must be signed in to change notification settings - Fork 7
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
Union Types: Inference and Checking. #5
Comments
I wrote something 3 years ago which may or may not be relevant (and may or may not have been correct, as I've learned a lot since I wrote that). |
@shelby3 There is more than one way to type this, which is generally seen as bad:
The problem is we don't know which type to give to |
@shelby3 I read the quiz, but I don't think it is relevant as we are not considering widening here, but which variant above should be used. In some regards, the third type seems to be the correct one, as given:
because we would need a subsumption rule that allowed:
To be passed to an argument where The problem is we will need expansion variables in the types to do it properly. |
@keean wrote:
The issue is I presume related to principal typings1. Remember we had a related discussion before in private messages in May on the Rust forum, about how to infer types that end up being recursive (like two mirrors pointing at each other). And my comment then was that if we require the containing function to have declared types, then we should be able to always resolve the locally inferred types within the containing function. Afaik, ML and Haskell allow the programmer to elide the types from top-level functions, thus making inference much more difficult when first-class, higher-order features are added moving away from the origin of the Lambda Cube. Seems we won't have that problem.
|
The paper you refer to only allows rank1 intersection types, and does not specifically deal with union types. To allow full intersection types will require expansion variables. I have written type inference with expansion variables before, but it was quite a while ago. Maybe we restrict ourselves to rank1 for now, infact I will probably start with rank0 that was the most recent thing I was working on. This allows intersection/union types in the context. The way I was thinking of doing this, because only exported functions need type signatures, is that we have a type-signature for a module much like an interface, which is then implemented. Something like:
This makes me think we need to sort the function syntax before doing more on inference. I am going to start a new issue. |
Afaics the lack of sufficient constraints will never exist, i.e. those cases as principal typings, if all top-level lexical scope functions arguments are required to have their arguments annotated with type declarations. We agreed that all "exported" functions would be required have their arguments annotated with type declarations, but we haven't yet discussed requiring that for all top-level lexical scope functions. Functions declared within the lexical scope of functions wouldn't need to be annotated, because they can only access instances within their top-level enclosing lexical scope, so the necessary constraints will exist for the inference to be decidable. However, I am not knowledgeable about if there is an existing inference algorithm for us to use. |
@shelby3 I have an novel inference algorithm that I like, that is capable of supporting intersection and union types with full expansion variables. The current version check into git here https://github.com/keean/Compositional-Typing-Inference It has some novel properties, it can type any code fragment (even with free-variables) independently and the types are composable, meaning two fragments can be combined without retyping the fragments themselves. It is HM like, but has principal typings. I will try and find the old version with expansion variables, and then I can port from C++ to JavaScript, which should remove all the memory management boilerplate. |
Again for readers' benefit, I will to link to what sum, product, and recursive types are. You are asking me if we will have recursive types in ZenScript and if so, what are the implications especially on inferring non-annotated types. For data types (not typeclasses aka Rust
You have expressed polymorphism. If we want to pass an However, the above has the problem that it can't be extended with new variants because it is necessarily If we prefer to have that remain open to extension of new variants (i.e. not So the other way to do that without
So with the second form I think the inference is much easier? |
Yes, the second form is what I would want, although we need to decide on the keywords to use, and also whether to give the self type special status. For example Rust uses Personally I think we should avoid |
@shelby3 wrote:
So the other way to write that is with an alias so it can written in shorter form every where:
I don't know we should allow the following?
Is it confusing? Edit: is our general rule that type parameters can only be bounded by typeclasses, not by data types? |
The way I have written these types is like this:
This is a recusive type, usable anywhere like this:
Or you can have a type alias which is just a short way of writing the same thing:
I think the general rule should be types are constrained by typeclasses, however I think set-subsumption is fine, so that we can see (Int | String) as being a set of types {Int, String} such that passing a String where a {Int, String} is okay. |
@keean wrote:
It is more verbose, but it is more clear. I opt for readability (clarity) when the additional verbosity is minimal. So I agree with your idea. If we use (Java/C++ angle I was actually confused for a few moments when I saw the
Not all types. We still need to pass data types around. A union of data types for example.
That doesn't apply to typeclasses as bounds on type parameters. Remember we decided upthread that unions of typeclasses don't make any sense because they aren't tagged at runtime. Agreed for unions of data types. |
@shelby3 I have written a lot in both styles, my only objection to '<' and '>' is that they are not really brackets and don't often get bracket matching in UI, and cause problems with cut and paste into HTML. I think there are four choices: Java style: So which is the best option? I think we should move this sub-topic to a new discussion: #7 |
Here's a problem with (anonymous) union types, given the following:
what is the type?
The text was updated successfully, but these errors were encountered: