The enum type inference problem is easily solved with identifier types
FeepingCreature
feepingcreature at gmail.com
Fri May 12 09:17:00 UTC 2023
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...)
More information about the Digitalmars-d
mailing list