digitalmars.D - The enum type inference problem is easily solved with identifier types
- FeepingCreature (40/40) May 12 2023 I just saw the ETI rejection over in Announce, and I just wanted
- Richard (Rikki) Andrew Cattermole (7/7) May 12 2023 A nice side effect of this solves None value for a sumtype.
- Sebastiaan Koppe (7/14) May 12 2023 I guess you can make enums too:
I just saw the ETI rejection over in Announce, and I just wanted to note that there's a handy feature in Neat (my lang), that would make this very simple. Neat has Identifier Types. An identifier is an expression of the form `:word`. The type of `:word` is `:word`, ie. identifiers do double-duty as types and expressions. The only value that can be assigned to a variable of type `:word` is `:word`; it is a type with a size of 0, like `void`. Identifier types were mostly introduced to allow disambiguating sumtypes: `void sleep((:delay, long seconds | :until, long seconds_since_epoch) target)`. But here they give us an unexpected upside. In terms of effort, it would be extremely easy (though I haven't done it yet) to say that an identifier can implicitly convert to an enum iff the enum contains a member with the same name as the identifier. What are the advantages of this? There is zero need to complexify the compiler by defining contexts in which a type can be inferred. There is *no impact* on type inference in this feature. The type of `:Dog` is perfectly unambiguous: it's `:Dog`. It so happens that a value of this type can implicitly convert to `enum Animals { Dog, Cat, Pigeon, }`, but this just uses the well-established implicit conversion system, and when it fails you get a nice readable error. Now, this is one instance where a rich typesystem hangs together in a way that D's relatively sparse typesystem does not. Consider the following: `Animal[] animals = [:Dog, :Cat];`. What is the type of the array literal? Since we don't know we're assigning to `Animal[]`, D would error here because it cannot unify `:Dog` and `:Cat`; they're different types. In Neat, because we have built-in sumtypes, we can just say the type is `(:Dog | :Cat)[]`, and then notice that oh yeah, this can still implicitly convert to `Animal[]`: because every member of the sumtype is implicitly convertible, the sumtype is implicitly convertible. But even without this, identifier types would allow implementing ETI without making the overall language design any more complex - they add a built-in type, but they don't change the existing language semantics at all. (If we had `opImplicitCast(T)`, we could implement identifier types in a library...)
May 12 2023
A nice side effect of this solves None value for a sumtype. ```d sumtype Foo = string | :None; ``` Add a little bit of semantic to make it the default when its present in set and we're good to go. I like it.
May 12 2023
On Friday, 12 May 2023 at 09:40:23 UTC, Richard (Rikki) Andrew Cattermole wrote:A nice side effect of this solves None value for a sumtype. ```d sumtype Foo = string | :None; ``` Add a little bit of semantic to make it the default when its present in set and we're good to go. I like it.I guess you can make enums too: ``` sumtype dir = :Left | :Right; ``` :D
May 12 2023