5 ms·
When I found sum types (in Haskell) I could not believe they had not been part of any prior language I'd learned. You can kind of fake them with inheritance but
by Jeff_Brown 7y ago
When I found sum types (in Haskell) I could not believe they had not been part of any prior language I'd learned. You can kind of fake them with inheritance but it's awkward, and you don't get totality checking, and you can't close the set of alternatives, so a new descendent added later can break things.
- Filligree 7y agoThey're included in Rust. But Rust of course feels very much like a strict-by-default Haskell in some ways. (Now with optional laziness.)
- uryga 7y agoi had no idea rust supported laziness! how does that work?
- cies 7y agoI think he refers to async recently landing in Rust. Here the Rust book mentions it: > async bodies and other futures are lazy: they do nothing until they are run. https://rust-lang.github.io/async-book/03_async_await/01_chapter.html https://rust-lang.github.io/async-book/03_async_await/01_cha... I just read it, and thought it was odd. I don't understand how Rust's async relates to a laziness as in Haskell's laziness.
- steveklabnik 7y agoIterators are also lazy. All of these things build up some form of computation that doesn’t execute until later. Until then, they’re represented by some kind of data structure.
- zozbot234 7y ago> I could not believe they had not been part of any prior language I'd learned. Huh? They're part of Pascal (known as variant records) and plenty of other languages besides. It's mostly C that lacks them, and even then you're just expected to implement them yourself, for maximum efficiency.
- akavi 7y agoThey're not present in the dominant statically typed languages (C/C++/C#/Java/Go) and not really a thing in dynamic languages generally, and so the vast majority of programmers never encounter the concept.
- pmontra 7y agoWell, Pascal has been dominant for a short time before C and its family really took off. But that was such a long time ago that I kind of forgot about it. C (without ++) was nice because you could write code without too much boilerplate compare to Pascal and it was noticeably faster (computers were slow.) However any mistake with pointers could crash the computer if it was a DOS PC and not a UNIX workstation.
- LessDmesg 7y agoThis might help explain why the dominant statically-typed languages are so hated. It's easy to choose Python when those languages are too clumsy to express a closed tagged union. This gives an undeserved bad rep to statical typing as a whole, when the solution is obvious to anyone familiar with algebra. Sum types are to product types what addition is to multiplication: if your language has one, why not have the other one? Answer that one, Bjarne Stroustrup!
- thestoicattack 7y agoC++ has std::variant, but that's pretty new.
- Sniffnoy 7y agoMy understanding is that's not really a sum type, though -- e.g., you couldn't use it to add a type to itself, only to add distinct types to each other.
- edflsafoiewq 7y agoNo, you can add a type to itself (that is a pain in the ass though). You might be thinking of the fact that it may not hold a value (eg. if an exception is thrown while moving into it), but they made it as close to a sum as they could given the nature of C++.
- LessDmesg 7y agoEven Haskell doesn't get it right: there are no exhaustiveness checks on pattern matches (something OCaml has), and while sum types provide closed unions, getting open unions is clunky (have to use typeclasses). OOP languages are imperfect in the opposite direction: open unions out of the box (inheritance) but no closed unions and no pattern matching. Seems language authors on the whole are bad thinking design spaces through. "The user might want any of three simple things X, Y, or Z, so let's choose the one that our language will support well, the one it will kind of support, and the one it won't support whatsoever just for the hell of it".
- whb07 7y agoHaskell does have exhaustive checks. Its just a compiler flag which isn't default turned on (this kills me).
- sjakobi 7y ago> Even Haskell doesn't get it right: there are no exhaustiveness checks on pattern matches Just enable -Wincomplete-patterns or -Wall!
- fauigerzigerk 7y agoIt's just a warning, and it's opt-in. I would say that counts as not getting it right.
- hcarvalhoalves 7y agoCan you please elaborate with some examples what you mean by "closed unions" and "open unions" here? I would appreciate a lot.
- kccqzy 7y agoWe say a sum type is "open" is more alternatives can be added later (or some alternatives can be removed later), perhaps in a different translation unit or a different library. We say it is "closed" if all alternatives must be specified at the definition, no alteration allowed. For example if you write this in Haskell data PrimaryColor = Red | Green | Blue colorToInt Red = 1 colorToInt Green = 2 colorToInt Blue = 3 it is closed because future code can't add more alternatives. Instead you must simulate it using type classes, with a wildly different syntax, and (some would say) a hack. Or define a different sum type that wraps the above. OCaml on the other hand supports the above perfectly with a slightly different syntax, but it also supports polymorphic variants (not to be confused with a Haskell sum type that's polymorphic because of a type variable like Maybe) which are lighter weight. For example you can write a function that takes different "constructors" without necessarily giving a definition for the type or listing all alternatives: let color_to_int = function | `Red -> 1 | `Green -> 2 | `Blue -> 3 Notice I never defined any type for the three colors! If you wish, you can mention the type: [< `Red | `Green | `Blue ] or give it an alias to make it look more normal. But you can add (with some limitations) or remove more things to this variant later on. To me, though, the most intuitive way of understanding this is to think of the first as nominal typing, whereas the second is structural typing.
- madhadron 7y agoI feel lucky that I learned Standard ML among the early languages I learned as a teenager, which got me into this mindset. That was way back before the monadic revolution.
- ww520 7y agoC has Union, while not exactly the same as adt, the essential idea is the same.
- gowld 7y agoA C union is a sum, but not much of a type, since it's never checked (not even at runtime like Python) and using it wrong in your code will silently corrupt your program.