6 ms·
Enums and sum types seem to be related. In the code you wrote, you could alternatively express the Hot and Cold types as enum values. I would say that enums are
by throwaway143829 2y ago
Enums and sum types seem to be related. In the code you wrote, you could alternatively express the Hot and Cold types as enum values. I would say that enums are a subset of sum types but I don't know if that's quite right. I guess maybe if you view each enum value as having its own distinct type (maybe a subtype of the enum type), then you could say the enum is the sum type of the enum value types?
- randomdata 2y ago> Enums and sum types seem to be related. They can certainly help solve some of the same problems. Does that make them related? I don't know. By definition, an enumeration is something that counts one-by-one. In other words, as is used in programming languages, a construct that numbers a set of named constants. Indeed you can solve the problem using that: type Temperature int const ( Hot Temperature = iota Cold ) func SetThermostat(temperature Temperature) { switch temperature { case Hot: fmt.Println("Hot") case Cold: fmt.Println("Cold") } } But, while a handy convenience (especially if the set is large!), you don't even need enums. You can number the constants by hand to the exact same effect: type Temperature int const ( Hot Temperature = 0 Cold Temperature = 1 ) func SetThermostat(temperature Temperature) { switch temperature { case Hot: fmt.Println("Hot") case Cold: fmt.Println("Cold") } } I'm not sure that exhibits any sum type properties. I guess you could see the value as being a tag, but there is no union.
- lelanthran 2y agoUnfortunately, this: const ( Hot Temperature = 0 Cold Temperature = 1 ) Isn't really a good workaround when lacking an enumeration type. The compiler can't complain when you use a value that isn't in the list of enumerations. The compiler can't warn you when your switch statement doesn't handle one of the cases. Refactoring is harder - when you add a new value to the enum, you can't easily find all those places that may require logic changes to handle the new value. Enums are a big thing I miss when writing Go, compared to when writing C.
- deleted 2y ago[deleted]
- randomdata 2y ago> Isn't really a good workaround when lacking an enumeration type. Enumeration isn't a type, it's a numbering construct. Literally, by dictionary definition. Granted, if you use the Rust definition of enum then it is a type, but that's because it refers to what we in this thread call sum types. Rust doesn't support "true" enums at all. > The compiler can't complain when you use a value that isn't in the list of enumerations. Well, of course. But that's not a property of enums. That's a property of value constraints. If Go supported value constraints, then it could. Consider: type Temperature 0..1 const ( Hot Temperature = 0 Cold Temperature = 1 ) Then the compiler would complain. Go lacks this in general. You also cannot define, say, an Email type: type Email "{string}@{string}" Which, indeed, is a nice feature in other languages, but outside of what enums are for. These are separate concepts, even if they can be utilized together. > Enums are a big thing I miss when writing Go, compared to when writing C. Go has enums. They are demonstrated in the earlier comment. The compiler doesn't attempt to perform any static analysis on the use of the use of the enumerated values because, due to not having value constraints, "improper" use is not a fatal state[1] and Go doesn't subscribe to warnings, but all the information you need to perform such analysis is there. You are probably already using other static analysis tools to assist your development. Go has a great set of tools in that space. Why not add an enum checker to your toolbox? [1] Just like it isn't in C. You will notice this compiles just fine: typedef enum { Hot, Cold } Temperature; void setThermostat(Temperature temperature) { switch (temperature) { case Hot: printf("Hot\n"); } } int main() { setThermostat(10); }
- lelanthran 2y ago> but all the information you need to perform such analysis is there. No, it isn't, unlike C, in which it is. The C compiler can actually differentiate between an enum with one name and an enum with a different name. There's no real reason the compiler vendor can't add in warnings when you pass in `myenum_one_t` instead of `myenum_two_t`. They may not be detecting it now, but it's possible to do so because nothing in the C standard says that any enum must be swappable for a different enum. IOW, the compiler can distinguish between `myenum_one_t` and `myenum_two_t` because there is a type name for those. Go is different: an integer is an integer, no matter what symbol it is assigned to. The compiler, now and in the future, can not distinguish between the value `10` and `MyConstValue`. > Just like it isn't in C. You will notice this compiles just fine: Actually, it doesn't compile "just fine". It warns you: https://www.godbolt.org/z/bn5ffbWKs https://www.godbolt.org/z/bn5ffbWKs That's about as far as you can get from "compiling just fine" without getting to "doesn't compile at all". And the reason it is able to warn you is because the compiler can detect that you're mixing one `0` value with a different `0` value. And it can detect that, while both are `0`, they're not what the programmer intended, because an enum in C carries with it type information. It's not simply an integer. It warns you when you pass incorrect enums, even if the two enums you are mixing have identical values. See https://www.godbolt.org/z/eT861ThhE https://www.godbolt.org/z/eT861ThhE ?
- nyssos 2y agoEnums are exactly sums of unit types (types with only one value).
- randomdata 2y agoTraditionally, enums have been a single number type with many values (initialized in a counted one-by-one fashion). Rust enums are as you describe, as they accidentally renamed what was historically known as sum types to enums. To be fair, Swift did the same thing, but later acknowledged the mistake. The Rust community doubled down on the mistake for some reason, now gaslighting anyone who tries to use enum in the traditional sense. At the end of the day it is all just 1s and 0s. If you squint hard enough, all programming features end up looking the same. They are similar in that respect, but that's about where the similarities end.
- lsaferite 2y agoRegardless of the rest of this thread, I appreciate this comment. It helped crystalize 'enum' in the context of 'sum' for me in a way that had previously been lacking. Thanks.