-
Notifications
You must be signed in to change notification settings - Fork 455
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
Support coercing string to elgible untagged variants #6443
Conversation
This is fine as long as a catch-all case with string payload exists. |
Not sure I understand the context fully, but how about this case in the runtime? @unboxed
type x = One | Two
let x = "Hello"
let y = (x :> x)
let f = switch y {
| One => "hollo"
| Two => "bollo"
}
// Console.log(f) result ??? |
It's indeed super niche and I've opted to only support strings here, while we could theoretically also support floats. But, it's quite useful in everyday work, because it gives the developer a "free" (DX wise) "variant from string" style function, where the current alternative is either an identity cast, or manually enumerating all strings and mapping them to the correct variant constructors. So, here we piggy back on the pattern match compiler already doing all of that work for us anyway. "Variant from string" functions have a ton of use cases of course, since you need them anytime you want to decode a string to variant. Which is often in the JS world, since so much is stored as strings. A few examples of concrete use cases:
I will say though that this is approaching "weird" territory and feels like an advanced feature. All in all though I think the benefits overweigh the costs. |
This is a type error because there's no "catch all" constructor with a |
@unboxed
type x = One | Two
let x = "Hello"
let y = (x :> x)
let f = switch y {
| One => "hollo"
| Two => "bollo"
| _ => "hello"
} Would this code be compiled? |
I read the PR again, then it seems not compiled. |
What I had in mind as super niche, is having a catch-all case |
@cristianoc yeah that's a good point. If we ever were to implement the "subtype matching" (lack of a better name) for variants that polyvariants has, one could pretty conveniently achieve decoding into things without default cases too: @unboxed
type myVariant = One | Two
@unboxed
type withUnknownCase = | ...myVariant | Unknown(string)
let myVariantFromString = (str: string): option<myVariant> => {
switch (str :> withUnknownCase) {
| ...myVariant as value => Some(value)
| Unknown(_) => None
}
} |
A better example, for the case |
No I'm not thinking about weird catch-all cases. I'm thinking about what people use every day. |
There is still a |
af7279c
to
3ee079d
Compare
"All variant construtors must be coercable to string " Why? |
Good point, thinking of it again that's not needed, it's only needed that it's unboxed and has a catch-all string case. |
…s long as there is a catch all case
@cristianoc removed the requirement for all variant constructors to be coercable to string. |
Adds support for a very specific (but useful) coercion - from
string
to an unboxed (elgible) variant:This works because the variant is unboxed, and because there's a "catch all" unboxed
string
constructor in the variant, that will catch any provided string that doesn't map toOne
orTwo
.Criteria for this coercion to work:
string