5 ms·
so, um, unions? i have to say that in many years of programming, i have almost never needed to use such types.
by zabzonk 4y ago
so, um, unions? i have to say that in many years of programming, i have almost never needed to use such types.
- nicoburns 4y agoDoes your code ever contain class hierarchies with a fixed set of classes? Or variables where certain values have special case meaning? Those are the cases where Sum Types make things immeasurably nicer than the alternatives.
- zabzonk 4y ago> Does your code ever contain class hierarchies with a fixed set of classes? no - one of the advantages of OO programing is that class hierarchies (should you feel the need to use them, which mostly i do not) can be expanded. or indeed contracted. > Or variables where certain values have special case meaning? very, very rarely (i would say never, in my own code) but of course we have the null pointer as a counter-example. to which i can say: don't use raw pointers.
- jjnoakes 4y agoDo you have any large open source code bases that you could share?
- kaba0 4y agoThe Visitor pattern, which is a must in certain niches is exactly analogous to pattern matching over a sum type, and I am fairly certain that I can objectively say that the latter is a million times more readable and maintainable. It doesn’t make OOP obsolete, though, at all. Certain other areas are better expressed as hierarchies, e.g. GUI nodes.
- dralley 4y agoTagged unions with exhaustiveness checking, built into the language in a fairly deep way. Very different from what would come to mind for a C or C++ developer who hears the word "union".
- burntsushi 4y agoNope, not unions. Sum types. Sum types would be more analogous to tagged unions or discriminated unions. > i have almost never needed to use such types Well sure. When is an abstraction "needed"? Before Fortran, nobody "needed" a programming language either. So is a programming language necessary? That's the funny thing about the word "need." It has very narrow application, and it's precisely why I didn't mention the word a single time in my top level comment.
- zabzonk 4y ago[flagged]
- deleted 4y ago[deleted]
- cornstalks 4y agoThe union part is just an (obvious) optimization. An implementation detail. Sum types are not required to use a union; they can be implemented without using a union.
- zabzonk 4y agohow, exactly?
- cornstalks 4y agoBy using a struct with lazily initialized members, for example.
- zabzonk 4y agoif that is your example, provide some code.
- cornstalks 4y ago
- edgyquant 4y agoI can’t imagine not having the ability for a variable to be one of multiple potential types. I could probably work around it, sure, but why would you want to?
- zabzonk 4y agoi can't imagine why you would want that. for example, why would i want something defined as an integer hold something other than an integer? this is how strongly-typed languages work.
- Twisol 4y agoScott Wlaschin's "F# For Fun and Profit" website is a great resource for strongly-typed (yes) data modeling with sum types as a fundamental tool. https://fsharpforfunandprofit.com/series/designing-with-types/ https://fsharpforfunandprofit.com/series/designing-with-type... By the third entry in the linked series, we've motivated the use of a sum type with three variants in the example domain model.
- lmm 4y agoYou definitely want an integer to always be an integer, but you often want to represent "A or B". E.g. user has a contact method that's a phone number or an email address. Result of validation is a validated value or a failure message.
- cmrdporcupine 4y agoThe C++ (or Java etc) way to do many of the kind of things people do with Rust pattern matching & sum types would be via OO subtyping polymorphism. e.g. classic visitor pattern, etc. Way more verbose and awkward, and scatters the logic all over the place. Enums + switch is the other, and far less powerful.
- thom 4y agoOr, for the case of errors, with exceptions, which happen to have their own very limited pattern matching syntax.
- kaba0 4y agoI swear I am not paid to shill for Java or anything…, but Java did get sum types recently, and it’s quite good. They made it in a backwards compatible manner by sealed classes that list all of its subtypes. Switch expressions were also implemented, and they can exhaustively match on the given sum type. Pattern matching is quite limited as of now (only usable with records), but it is coming.
- cmrdporcupine 4y agoI should take a look. I kind of have a nostalgic interest in looking back at the JVM again, as 10 years ago it was my main career. The problem with Java was always that it has moved so slowly in acquiring nice things. The actual core runtime is amazingly well engineered.
- mgsloan2 4y agoIn my experience with languages that lack concise sum types and pattern matching, you end up with data types that have lots of implicit invariants. If you find yourself writing docs or thinking in your head things like "Field X is only set if field Y is true" or "If field X is non-null then field Y must be null and vice-versa", then these are indications that sum types would model the data better. Then these invariants can be followed by construction, and it becomes clear what's available at data access - great for interface clarity, robustness, dev tools, morale, etc. Relatedly, storing booleans is a smell, imho typically an enum or sum type is always better in languages that have concise syntax for these. True and False are meaningless without context, and so can easily lead to errors where they are provided to a different context or generally misused due to a misunderstanding about the meaning.
- zabzonk 4y agoi agree with your first point, but if your type-system is sufficently strong to express this, i'd like to see an example. i agree completely with your second point - passing around or storing booleans is usually horrible.
- mgsloan2 4y ago> if your type-system is sufficently strong to express this No fanciness needed, just plain old sum types. It is certainly possible to express those invariants directly in languages with a dependent type systems or refinement types like in liquid haskell - see https://ucsd-progsys.github.io/liquidhaskell-tutorial/Tutorial_05_Datatypes.html https://ucsd-progsys.github.io/liquidhaskell-tutorial/Tutori.... It's typically much easier to reason about and use sum types, though. Of course these examples are trivial and silly, but I see instances of these patterns all the time in big co software, and of course usually the invariants are far more complex but many could be expressed via sum types. I've seen loads of bugs from constructing data that invalidates assumptions made elsewhere that could have been prevented by sum types, as well as lots of confusion among engineers about which states some data can have. > Field X is only set if field Y is true Original gnarly C style pattern: struct TurboEncabulatorConfig { // When true, the turbo-encabulator must reticulate splines, and 'splines' // must be non-null. When false, 'splines' must be null. bool reticulate_splines; struct Splines *splines; }; Rust (let's ignore pointer vs value distinction): enum TurboEncabulatorConfig { NonReticulatingConfig, ReticulatingConfig { splines: Splines }, } > If field X is non-null then field Y must be null and vice-versa. Original gnarly C style pattern: struct TurboEncabulatorConfig { // When non-null, lunar_waneshaft must be null. struct Fan *pentametric_fan; // When non-null, pentametric_fan must be null. struct Shaft *lunar_waneshaft; }; Rust: enum TurboEncabulatorConfig { PentametricTurboEncabulator { pentametric_fan: Fan }, LunarTurboEncabulator { lunar_waneshaft: Shaft }, }