Hacker News new | ask | show | jobs
by valenterry 1311 days ago
Not sum types. Those are union types. The difference is important, since if you work with two results (or two functions that return results) that use the same error-type you most often don't want to end up with a tuple of two times the same error but simply A<String, Error>.

Of course, if you care about which error is from which function, you can always easily do that by wrapping them into a sumtype, but in practice this is a rather rare use-case in application code at least.

2 comments

How would that work in a memory safe language? Rust does have (named) untagged unions already (using the `union` keyword), but they are unsafe to use because there is no way to know statically which of the possible variants a given value contains.
You can obviously only call common methods or have to pattern match later and have a way to tell them apart. If you can't tell them apart, the compiler will tell you and you need to tag them somehow.
> You can obviously only call common methods

That sounds like trait objects/dynamic dispatch/`dyn`, which comes with runtime costs.

> or have to pattern match later and have a way to tell them apart.

That "way to tell them apart" is a tag, which would make it a tagged union/enum, not an untagged union. Those already exist, though not in an anonymous flavour.

It does, but the developer decides. Also, errors are often propagated and only matched in exceptional cases, so I don't think the impact would be big.

> That "way to tell them apart" is a tag, which would make it a tagged union/enum, not an untagged union.

No. The difference is that a tagged union (sum type) is defined in advance but generally a union is not necessarily tagged but _can_ be tagged.

Example: say you have tagged union with 3 different types / tags A, B and C. You can now define an adhoc/untagged union that is A | C. That means, we can guarantee at compile time, that we will be able to tell A and C apart later. But it is still not the same, because the combination of A and C was decided adhoc and was not predefined by the developer anywhere necessarily - which is what makes it different from A, B, C which where specifically defined by the developer.

Unions don't have a discriminant. Anonymous Sum types have a discriminant, you just can't name it. Unions in Rust are unsafe because you can't tell what the underlying value will be.
Well, that depends. If the union consists of two types that share the same underlying structure, then obviously at runtime we can never know what the value is.

But otherwise we can. And this is something that we will know at compile-time, so we can prevent runtime-checks that would not work.

I must not be understanding what you're asking for because it sounds like anonymous sum types.
Maybe this is just about terminology.

But essentially, when it comes to union types, they behave like sets. The compiler merges them. (A | B) | (A | B) is the same as A | B. But for sum types (even anonymous ones such as tuples) the compiler can't merge them because that would lose information (if the result is from the first A | B or the second one). Instead, you end up with a nested structure.

Which one is desired depends on the use-case, but it's definitely different.

The problem is that if you have e.g.

    let x: u64|i32 = ...
It's impossible for the compiler to do anything with x without adding some kind of runtime type tag. The representations of those types are different.

But with something like OCaml's polymorphic variants, you could do e.g.

    let x: Big(u64)|Small(i32) = ...
and then switch on the tag (Big or Small) to determine what to do with the values.
> It's impossible for the compiler to do anything with x without adding some kind of runtime type tag.

Yes, in this particular case that's true. If the developer tries to do anything except maybe printing it for debug then the compiler will tell the developer so and the developer will have to switch to sumtypes / wrap it just like it is done in OCaml by default.

IIUC this kind of union would discriminate only on type.