Hacker News new | ask | show | jobs
by bPspGiJT8Y 999 days ago
> They are to enums what tuple types are to structs.

But this is just a generic sum type?

    data Sum a b = L a | R b
    infixr 5 type Sum as ⊕
    type E₂ a b z = a ⊕ b ⊕ z
    type E₃ a b c z = a ⊕ b ⊕ c ⊕ z
    -- and so on…

Here, `Eₙ` represents a sum type with at least `n` members indexed by their position, and `z` represents any type so that it's possible to keep extending the number of positions via further nesting. When you're done you set it to a type with no members:

    type E₃AndNoMore a b c = a ⊕ b ⊕ c ⊕ Void
I don't know Rust so I can't claim if it allows it, but I'm almost certain it does.
1 comments

> But this is just a generic sum type?

No, it's actually less generic. It's not determined by position but by type. For example `A | B | A` is the same type as `A | B`.

This is useful as a shorthand when you don't want/need a new type to represent your problem, similar to tuples.

So you're talking about untagged unions?

> This is useful as a shorthand when you don't want/need a new type to represent your problem, similar to tuples.

Yes this is handled perfectly by the generic sum type, you don't need untagged unions for this. Rust used to have Either in its standard library, but they removed it and kept Result only. Semantically they're the same (a ⊕ b) but Result's name implies it has something to do with some "results". Anyways nothing stops you from creating one yourself, or even using Result if you're fine with the weird-sounding name.

No, I am not talking about untagged unions. I don't understand your notation. To be concrete, I am talking about tagged, disjoint union type, that does not require naming a new type to use.

This is also not covered by the Either/Result type.

Rust supports untagged unions, but they cannot be matched (because they have no tag). An anonymous union would still be tagged internally, but would be less general purpose than the generic enum type.

> To be concrete, I am talking about tagged, disjoint union type

But you just said "For example `A | B | A` is the same type as `A | B`". How would this be possible for tagged union types?

> that does not require naming a new type to use

> This is also not covered by the Either/Result type

It's more probable that I'm just not understanding what you're talking about, but *the only* re-usable tagged union type similar to tuples is *the* sum type.

Let's say you're dealing coffee. People want it either with sugar or without sugar. You don't want to create a new sum type CoffeeFlavor? Fine, just use Either<Sugar, NoSugar>. This is *the* equivalent of a tuple. You need more than 2 options? No problem, Either<Sugar, Either<JustABit, NoSugar>>. I don't know what else could be a "anonymous tagged union".

Ah ok I think we're mixing up terms here - in the context of systems programming languages, a "tagged" union refers to an integer in front of a bag of bytes that holds the data of the "un tagged" union. Rust has both tagged (enums) and untagged (unions) union types.

What you're asking about is a discriminated vs non-discriminated union, and indeed, that's exactly what I'm talking about.

A | B |C is not the same type as Either<A, Either<B, C>> because Either<A, Either<A, B>> cannot type check as Either<A, B>.

But even if you want to argue that you can represent things that way, it misses the point. The goal is to remove complexity from the type hierarchy of the program, not add to it.

> because Either<A, Either<A, B>> cannot type check as Either<A, B>

Why would you want the former to type check as the latter? Where do you see the complexity?