3 ms·
One difference between this proposal and Rust enums (i.e. tagged unions) is that enums let you use the same type more than once with a different tag. Obviously
by saghm 5y ago
One difference between this proposal and Rust enums (i.e. tagged unions) is that enums let you use the same type more than once with a different tag. Obviously Go doesn't have generics yet, but something like `Result<String, String>` doesn't seem like it would be straightforward as a non-generic type either with a type set, since you don't have any way of differentiating between which "type" of string you might have. I _think_ this might be possible with a typeset by defining a newtype for one or both of the string types, but I haven't used Go in long enough that I don't remember if newtypes will implicitly convert to the type they wrap or not.
- masklinn 5y agoWith this proposal the variants are simply types themselves, so you'd have a struct Ok[T] and Err [T], and thus Result<T, E> would be something like interface Result[T, E] { for Ok[T], Err[E] } And there’s no issue with having T=string and E=string.
- cube2222 5y agoThey don't implicitly convert (though you can still use literals to create them). So yes, specifying Ok and Error string types should hypothetically work for this.
- pcwalton 5y agoYeah, the standard solution is to create a newtype for each such variant. I believe this is the preferred idiom in languages like TypeScript that have union types but not discriminated union types.
- brundolf 5y agoTypescript does have discriminated union types, you just have to use objects with a discriminating property which is a bit less ergonomic than the way those work in other languages. It's done this way to preserve TypeScript's goal of having little to no impact on runtime behavior
- ibraheemdev 5y agoI believe this would work with type sets: type Result[T any, E any] interface { T | E }
- lmm 5y agoIf T=int32 and E=int32, does this behave like int32 | int32? If so, how can you tell which it is? (Presumably you have generic code that needs to know whether this case is T or E). If not, that's pretty surprising.
- yutijke 5y agoNo. T | E should only accept T or E. If their underlying type is int32 then int32 will not be accepted. If we want to accept underlying types then we would need ~T | ~E. Either way this doesn't help since typesets cannot be used as normal interfaces, only generic constraints.