4 ms·
There is some runtime complexity here though. With both enums and sum types, if you want to differentiate the types at runtime, you need to include a discrimin
by MrJohz 3y ago
There is some runtime complexity here though.
With both enums and sum types, if you want to differentiate the types at runtime, you need to include a discriminant in order to be able to do that. Enums include that discriminant explicitly (that's what the `Token::Identifier(...)`/`Token::Number(...)` part represents). The memory layout for, say, a base identifier can consist only of the necessary fields for that identifies, but when it gets wrapped it will get an extra field that identifies which variant of the en it is.
With sum types you have two options:
* You always include a type tag directly in the representation (so a base identifier always has an extra byte or so of information with it). This is typically used in dynamic languages where the types are known at runtime anyway. I believe it's also the case in Java and I suspect other VM-based languages are similar.
* You dynamically generate the enums at compile time (so a base identifier doesn't have a tag, but if it's used in a `Identifier | Number` union, then a tag for that specific union gets added in).
The problem with the first is that it adds unnecessary runtime cost, because now every instance of any type has extra information in it that probably isn't needed. The problem with the second is that the creation and unwrapping of enum values becomes implicit, and you'll probably need to juggle your discriminants around more. Say I gave a function of type Identifier | Number -> Boolean | Identifier | Number, then should the discriminants for the Identifier and Number cases stay the same? Or do we need to add extra code to munge the input discriminants into output discriminants? In the first case, this adds a lot of complexity to the compiler (and may not in the general case be possible), in the second case we have runtime performance issues.
This is, I think, the point that the previous poster was getting at. If you have implicit discriminators, this will have an implicit runtime cost that may not always be easy (or possible) to avoid. That is the value of explicitly wrapping types in enums - the runtime cost can be minimised, and the developer is always aware of where that runtime cost appears.