Skip to content
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

Better Type Unions #13225

Closed
neelsudhakaran opened this issue Mar 25, 2023 · 3 comments
Closed

Better Type Unions #13225

neelsudhakaran opened this issue Mar 25, 2023 · 3 comments

Comments

@neelsudhakaran
Copy link

Discussion

Disclaimer: New Crystal developer, so this issue may lack a deeper understanding of the language. (P.S.—loving it so far!)

  • What aspect of the language would you like to see improved?
    Union Types are very wonky at the moment, especially in "complex" data structures.
  • What are the reasons?
    If you type a variable as a complex data type—say as an array or a map—you cannot assign it to a "pure valued" data structure even if logically it is valid.
  • Include practical examples to illustrate your points.
    The following example wouldn't work because you are trying to assign purely Int32 or Float64 hashes into a union hash. Logically however, all of the below hashes should be valid under the union. The same thing applies for arrays, and probably more data types that I simply haven't tried this with yet.
map : Hash(String, Int32 | Float64) = {
    "A" => 0,
    "B" => 0.5,
    "C" => 1,
    "D" => 1.5
}

map = {
    "A" => 0.1,
    "B" => 0.2,
    "C" => 0.3,
    "D" => 0.4
}

map = {
    "A" => 0,
    "B" => 4,
    "C" => 6,
    "D" => 8
}
  • Optionally add one (or more) proposals to improve the current situation.
    I've never coded a compiler before, but perhaps for union types with complex data structures, rather than comparing the raw data type, you do some kind of a recursive check to see that all values within it fit the union type spec? It sounds kind performance costly, I guess, but I presume this is what other languages (e.g. TypeScript) do?
@Blacksmoke16
Copy link
Member

Blacksmoke16 commented Mar 25, 2023

You can accomplish this by being more explicit with your hash literal to tell the compiler that it allows values/keys other than those in the literal.

map = {
    "A" => 0.1,
    "B" => 0.2,
    "C" => 0.3,
    "D" => 0.4
} of String => Int32 | Float64

or

map = Hash(String, Int32 | Float64){
    "A" => 0,
    "B" => 4,
    "C" => 6,
    "D" => 8
}

Ref: https://crystal-lang.org/reference/1.7/syntax_and_semantics/literals/hash.html#generic-type-argument

@straight-shoota
Copy link
Member

straight-shoota commented Mar 25, 2023

Duplicate of #9797.
The underlying issue isn't actually union types, this is an application for covariance/contravariance which is tracked and explained in #3803. If you have any questions, feel free to ask. But I'm closing this as a duplicate.

@straight-shoota straight-shoota closed this as not planned Won't fix, can't repro, duplicate, stale Mar 25, 2023
@neelsudhakaran
Copy link
Author

Thank you! I appreciate the help :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants