6 ms·
I may be wrong, but I don't think this is what people mean by 'sum types'. I was expecting union types (e.g., https://www.typescriptlang.org/docs/handbook/unio
by amitport 6y ago
I may be wrong, but I don't think this is what people mean by 'sum types'.
I was expecting union types (e.g., https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#union-types https://www.typescriptlang.org/docs/handbook/unions-and-inte... or https://dotty.epfl.ch/docs/reference/new-types/union-types.html https://dotty.epfl.ch/docs/reference/new-types/union-types.h... )
I guess enums are a type of sum type, but seems this is more specifically about enums
- edflsafoiewq 6y agoUnion types aren't sum types. One difference is A | A = A, but A + A = 2 * A.
- muglug 6y agoI think the use of an enum (in the Rust example) makes this a sum type situation: https://tonyarcieri.com/a-quick-tour-of-rusts-type-system-part-1-sum-types-a-k-a-tagged-unions https://tonyarcieri.com/a-quick-tour-of-rusts-type-system-pa...
- enricozb 6y agoI believe another word for enums (in the Rust sense, not in the C++ or Java sense) are tagged unions.
- curryhoward 6y agoThat's right. It's unfortunate that Rust calls them "enums", since as you noted that term already had a well-established meaning in other languages, and the concept that Rust calls "enums" also had several existing names (sum type, coproduct type, disjoint union, and, more generally, algebraic data type) in the literature and in prior languages. Language designers: stop changing the meanings of words! I know you mean well and you're trying to tie unfamiliar ideas to familiar ones for beginners, but you end up causing more confusion for everyone in the long run.
- richardwhiuk 6y agoRust enums are also enums: enum Colour { Red, Blue, Green, } is fine.
- masklinn 6y agoMore than that: #[derive(Debug)] enum Colour { Red = 1, Blue = 2, Green = 4, } fn main() { println!("{:?}", Colour::Blue); println!("{}", Colour::Blue as u8); }
- curryhoward 6y agoWhen you say "Rust enums are also enums", that's not true in general. What is true is that _some_ Rust "enums" (like your `Colour` example) can be represented as traditional enums. You don't prove a universal quantification with a single example.
- richardwhiuk 6y agoAll enums are expressible as Rust enums.
- dan-robertson 6y agoEnum has one meaning in C family languages. Other languages may have different meanings. For example, in Haskell something is an enum if there is an invertible mapping between that type and (a contiguous subset of) the machine integers (with complications). In other languages the concept might correspond to (finite) recursively enumerable sets (ie you can list all their elements).
- masklinn 6y ago> It's unfortunate that Rust calls them "enums" Rust calls them enum to be familiar to people coming from C-family languages, which is a large target. > since as you noted that term already had a well-established meaning in other languages Rust enums "degenerate" to a C-style enum (except typesafe) as it can be repr'd to a number and it's possible to select the discriminant (if there's no associated data). > the concept that Rust calls "enums" also had several existing names (sum type, coproduct type, disjoint union, and, more generally, algebraic data type) in the literature and in prior languages. Pretty much none of which are actually part of the language e.g. in Haskell or OCaml the designator is `type`, and it's used for both sum types and product types: the sum type simply has a single constructor. But Rust doesn't use `type`, it uses `struct`. And a `struct` with multiple variants doesn't make sense.
- renewiltord 6y agoRust enums are full union types. i.e. while each possibility in a (say) Java enum must be of the same type, each possibility in a Rust enum can be of a different type. i.e. https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=3e9da02167dde3435735fee270b9dd24 https://play.rust-lang.org/?version=stable&mode=debug&editio...
- DaiPlusPlus 6y agoHowever, Rust's enum-type members are still named - to my knowledge you can't have anonymous enum type members in Rust. In the example you gave, the type-of `left` is still `SumType::Left` instead of being just `String`. I'm not too familiar with Rust to say, but I don't consider this to be a syntactically zero-cost abstraction (even if the wrapper-types are elided by the compiler) because we still have more keyboard typing to do than we should be doing, imo.
- renewiltord 6y agoAh, that's to enable you to have multiple members that could hold `String` values. Yeah, it comes with the (syntactic) cost that you have to identify the member.
- ATsch 6y agoIn practice that's really not a problem because of rust's great pattern matching that easily lets you extract even deeply nested values.
- millstone 6y agoSimple way to think about it is plus. Sum plus sum increases, union plus union does nothing. 1. A union type is like int | double. It means the value is one of a set of possible types. And it's a true set: `int | int | double` is indistinguishable from `int | double`. 2. A sum type is a new type built from a list of other types, which assigns a 'tag' to each possible list element, like a Rust enum. The tags are not themselves types: they are like a struct field name. It's quite possible to have a sum type with N tags, each wrapping `int`. So with this understanding Rust has sum types but not union types, while TypeScript has union types but not sum types.
- amitport 6y agoThanks! This clarifies the situation
- paavohtl 6y agoIt is possible (and popular) to have sum types in TypeScript by manually adding a tag, though. type Maybe<T> = | { kind: "Some", value: T } | { kind: "None" }
- carlmr 6y agoThis is also why sum types are often referred to as tagged unions. They are a special case of a union, in Rust's case with support from the type system.
- a_humean 6y agoYep, Typescript's control flow analysis, type literals, and union types allow us have tagged unions/sum types. Probably its best feature.
- tybit 6y agoTypeScript does have tagged unions in addition to untagged ones https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#tagged-union-types https://www.typescriptlang.org/docs/handbook/release-notes/t...
- 6y ago
- guerrilla 6y agoA sum type is a tagged union [1]. In C, a sum type can be modeled by the combination of an enum and a union. The enum would tell you which field of the union you should use. In Rust, enum's subsume unions and enums of C. This is analogous to a a disjoint union [2] in set theory. Notice that in both cases you have a pair of data. Sum types and disjoint unions are both instances of coproducts in category theory, by the way. 1. https://en.wikipedia.org/wiki/Tagged_union https://en.wikipedia.org/wiki/Tagged_union 2. https://en.wikipedia.org/wiki/Disjoint_union https://en.wikipedia.org/wiki/Disjoint_union
- lostmyoldone 6y agoAccording to the tagged union Wikipedia you referenced, a disjoint union is also considered a tagged union. Whether or not that's actually a correct description within the vernacular of computer science, I don't know. "In computer science, a tagged union, also called a variant, variant record, choice type, discriminated union, disjoint union, sum type or coproduct, ..."
- guerrilla 6y agoThey're all what you call isomorphic to eachother, which means roughly any adequate mathematical model of one can mapped to any other.
- hellofunk 6y agoEven the word "enum" is quite overloaded; i.e. compare Swift's robust class-like enums with those of C or C++.
- PhineasRex 6y agoThis is just a difference between named and anonymous types, really. This is very similar to named functions vs lambda functions, both provide the same exact functionality but avoiding superfluous identifiers makes programming more ergonomic. More specifically sum types in Rust must also be tagged, meaning you need to explicitly construct and deconstruct them. This aspect is along the type-alias vs newtype axis which gets into structural vs nominative typing and the trade-offs therein. So yes, Rust enums and Typescript union types are both exactly sum-types and the differences are due to the surrounding decisions made about the languages. Rust's sum types are named and tagged, Typescript's are anonymous and untagged, but they're both sum types.
- nybble41 6y ago> So yes, Rust enums and Typescript union types are both exactly sum-types… As others have pointed out, untagged unions are not sum types because the union of a type with itself has no effect, whereas adding a type to itself yields twice as many possible values. Untagged unions can function as sum types when there is no overlap between the members, but not in the general case. To illustrate the difference: You can construct every possible algebraic type as some combination of void (no values), unit (one value), sum (|A + B| = |A| + |B|), and product (|A * B| = |A| * |B|). This does not work if the sum type is replaced with an untagged union. You can't even get as far as constructing the equivalent of the boolean type; while |Unit + Unit| has two distinct values, |Unit ⋃ Unit| only has one value.
- whateveracct 6y agoI guess technically what people want us algebraic types. Sums of products. Just sums alone are just enums.
- masklinn 6y ago> I may be wrong, but I don't think this is what people mean by 'sum types'. It is. > I was expecting union types (e.g., https://www.typescriptlang.org/docs/handbook/unions-and-inte.. https://www.typescriptlang.org/docs/handbook/unions-and-inte.... or https://dotty.epfl.ch/docs/reference/new-types/union-types.h.. https://dotty.epfl.ch/docs/reference/new-types/union-types.h.... ) Union types are basically an anonymous form of sum types. In the same way tuples and structs / records are both forms of product types. Statically typed languages which support sum types generally only support the named version (because it tends to be more useful and powerful). > I guess enums are a type of sum type, but seems this is more specifically about enums Depends on the language, C's enums are not types at all, Java's or C++'s are product types. Technically enums (or more generally tagged unions, which is what Rust's enums are) is a superset of sum types as you can have multiple variants of the same type, but that's not leveraged here.
- curryhoward 6y ago> Union types are basically an anonymous form of sum types. This is false on multiple levels. First, being a sum type has nothing to do with the type being named vs. anonymous. What makes a sum type a sum type is that it's a categorical coproduct, whether you give it a name or not. Second, sum types are synonymous with _disjoint_ (i.e., tagged) unions, not unions. Consider the union of boolean with itself. The result would be equivalent to boolean, because union is an idempotent operation. Disjoint union, or sum, would give you a type with 4 values instead of 2. > Technically enums (or more generally tagged unions, which is what Rust's enums are) is a superset of sum types as you can have multiple variants of the same type That just how sum types work (have you ever wondered why they are called "sum" in the first place?). You're thinking of union types.