| > You can always implement tagged unions in any language with untagged unions, so in a broad sense you can emulate sum types in situations where they make sense but use simpler code elsewhere I'm a bit confused now, since I don't see how this is related to the point I was making. You are right - with the exception that sumtypes are still more powerful since you cannot e.g. emulate GADTs with tagged unions, but for most cases in practice, I agree. Still, what's the point? I also think we have a general misunderstanding, since you are saying: > That works in Lisp where you can elegantly add language features with proper macros But Lisp is dynamically typed, so talking about union types is meaningless in a dynamically typed language. That doesn't make any sense to me in this context. And about C (which is statically typed): C does not have union types (and hence also no tagged union types). What C does have are (untagged) enums, but that's not the same thing. The crucial difference is that union types are ad-hoc whereas enums are statically defined. I think it is a bit confusing since C calls them unions - but in the context of this discussion it's important that they are very different things. E.g., with union types you can do: type union1 = string | int
type union2 = string | boolean
type union3 = union1 | union2 | float
// same as type union3 = string | int | boolean | float
The compiler must be able to resolve those things automatically. I'm hope I'm not completely mistaken here, But I believe there is no way to combine unions like this in C at the type-level. You would have to write those out by hand or generate the code. But if there is, please correct me.> This is compatible with old callers, even, who treat any nonzero result as failure and any zero result as complete success (the normal pattern in C). The idea or moviation was though that in a language with sumtypes (or tagged unions) the old callers would not be compatible. Trying to compile code against `function2` should fail. But it should not fail in an arbitrary way - it should fail by the compiler saying "hey, look, you handled the error case and the success case, but you also have to handle the partial-success case; and here is how the data you need to handle looks if it is partial-success: ...". That is what sumtypes give you, and I find that this enormously useful in practice. In a language without sumtypes you will not get this level of support by the compiler - that is the point I was trying to make. |