-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
[Analyzer] Add union types to Wasp #381
Comments
Additional thoughts:
|
@sodic and I discussed how to implement sum types in Wasp, here are some conclusions:
|
More thoughts:
|
To cover the use case from the issue's description (e.g., supporting both pages and routes for route OldLoginRoute { path: "/signup", to: LoginRoute }
route LoginRoute { path: "/signup", to: LoginPage } It should be enough to make changes inside More generally, our main goal is to never show unification errors to the user. Instead, we'll always construct a sum type and handle potential errors in the weakening phase as "Expected type X, got type Y". Let's say a user specifies a list value as Unification errors can currently only happen in lists. When encountering a list, we should find the most common supertype of all elements and infer that. Wasp will later check the inferred type against the required type. To make this change possible, it should be enough to change the function
|
While researching, I stumbled upon the discovery that we are actually implementing union types (not sum types). The difference comes from something we've touched on several times in an unrelated context. There are two kinds of unions:
In essence, a sum type is a union type with explicit labels. Here are several helpful resources on the subject:
By the way, several answers/comments in the above SO thread give a great answer to the question "Why doesn't Haskell support untagged unions?" Spoiler: you were on the right track with the reasoning that there would be massive inferred unions all over the place, but there's more to it. |
Thanks for sharing @sodic this is very interesting! Ok great, then let's call them union types! Interesting regarding Haskell -> I read what you shared and besides certain technical reasons, I understood it mostly comes down to cost / benefit ratio. It would not bring enough to Haskell to be worth the complexity it would introduce. Which makes sense to me! In our case though, I think it could be a good cost / benefit ratio, what do you think? |
Yes, it definitely makes sense for us. Haskell already has tagged unions, so they wouldn't be getting much out of adding untagged unions (i.e., tagged unions already cover most use cases). Since Wasp doesn't yet support any kind of unions, our cost/benefit ratio is very favorable. |
We won't "penetrate" into type constructors (e.g., dictionaries, tuples). For example:
It should be assignable to its supertype type T = { to: number | boolean }[]
let x = [{to: 1}, { to: true }] |
In this session we defined new Ones we make that work, next big step will be implementing an algorithm in Before that we will also probably want to take care of TODOs and write some tests. There is also Evaluator -> we will need to add support for UnionTypes there at some point, and figure out how are they deduced from AppSpec. |
We finished implementing Next step is updating the |
We started writing tests and should continue from Summary:
|
We fixed some of the tests!
|
Today we implemented tests for |
Next time: continue writing test for weaken, and then let's implement weaken. We also have a lot of TODOs sprinkled around. |
We wrote tests for |
Next step:
|
We removed |
We started looking into We traced where it is used, and found that its only place of usage is currently in The question was, is this needed? Can we just skip this part and instead of doing the weakening, which updates the types in typed expression tree to match the wanted type, can we just check that typed expression is a sub-type of wanted declaration type and that is it, don't do any weakening? So effectively we would refactor But, will that be a problem down the road then? Does Evaluator expect the typed expression in the declaration to match the declaration type, or can it just be its sub type? Therefore we next looked into the Evaluator, specifically how evaluation is implemented -> does it use that assumption or not. One interesting file is Then next we looked into What we did conclude though is that it might be a good idea to take a step back and start from the AppSpec side, implementing Union type there, via To conclude, there are main two directions to chase:
|
We started working on a new branch (branched out from main): https://github.com/wasp-lang/wasp/tree/filip-martin-weaken. The main idea is to first simplify (or completely get rid of) After we simplify the type inference (by making sure we don't traverse the AST twice and lose type information by weakening subexpressions after unification), we'll create a new branch for adding union types. |
We merged the PR that removes the weakening and instead introduces the explicit notion of subtypes! This will make this PR much simpler. For this PR we discussed we should continue in the following way:
|
If we have
route
and if it can point to eitherpage
or anotherroute
, how would this work right now in Wasp?We would have to say, in Wasp langauge definition, that
route
declaration type has three fields:path
:: Stringpage
:: Ref Pageroute
:: Ref Routeand then either
page
orroute
field need to be set, but both can't be set at the same time. However, this we can't capture in the type system and we would have to check for this later, either in some very late stage of Analyzer, or in the Generator itself.However, if we had sum types, then we could define it like this:
path
:: Stringto
:: Ref Page | Ref Routeand then this requirement would be captured by the type system!
I am not sure how hard would it be to implement sum type, at first thought it doesn't sound like it should be super hard, but I am not sure until we dive deeper into it.
This is not urgent but it would be cool to have!
The text was updated successfully, but these errors were encountered: