2 ms·
I’ve used C++ variants (from a couple of different libraries) a fair amount, and they are sort of union types, and I generally dislike it. The problem is that
by amluto 3y ago
I’ve used C++ variants (from a couple of different libraries) a fair amount, and they are sort of union types, and I generally dislike it. The problem is that logically identifying the contents based on type is confusing and refactors poorly.
Suppose I have an Identifier or a Number or a StringLiteral. To work intelligently, this needs Identifier and StringLiteral to be disjoint. This isn’t just a type theory issue —- it’s a semantic issue. What is “foo”? Is it an Identifier or a StringLiteral? What happens when I add a Filename (for including/embedding files in the future)?
Logically, the fact that an Identifier is encoded by a particular type is a bit of an implementation detail, and a good type system will catch errors. It’s the fact that it’s an identifier — that is, it’s purpose — that matters for semantics and for understanding the code, and union types (and C++ variants, for the most part) are very bad at exposing this.
- yakubin 3y agoMy issues with std::variant in C++ boil down to it being a runtime, not compile-time construct, and surprising interactions with implicit casts, especially in the case of primitive types. After that, unlike what I described about combining union types with lexically-scoped-newtypes, std::variant doesn't let you build sum types when you need them. You're stuck only with union types. > What is “foo”? Is it an Identifier or a StringLiteral? Normally, it's an identifier, since there are no quotes. If there is ambiguity about it, the lexical categories you're working with are ambiguous, which is a real issue. When designing a grammar, that should be avoided. Sadly, sometimes we're given a poor-quality grammar like in C, where some tokens can be interpreted both as headers and as string literals (but neither is a subset of the other) and can't do anything about it, but then you just need to decide which category you're going to assign to ambiguous cases (either one of two, or make a third one) and later you can disambiguate based on context. In any case, I don't consider it an issue of the tool, but an essential domain problem to be solved explicitly by the programmer.
- amluto 3y ago>> What is “foo”? Is it an Identifier or a StringLiteral? > Normally, it's an identifier, since there are no quotes. Sorry, I was vague. I don't mean the sequence f o o in the input or the sequence " f o o ". I mean the string (String, str, whatever your language calls it) containing the three letters f o o, which is stored in a union type. Sure, one can lexically-scoped-newtype it if the language supports it, but at that point, unless I'm missing something, it might as well be a sum type.