News for hackers. Stuff that matters.
Re:Go is boring, and that’s fantastic by atombender on Friday July 03, 2020 @01:41PM (#23725895)
My understanding is that there's no real distinction between "sum type" and "union type" as such.

I may be wrong, but whether you have an indirection through a type constructor or not doesn't alter the meaning of the union. In the fictional Go syntax, you could also have the same indirection:

  type Reader struct { R io.Reader }
  type ReaderAt struct { R io.ReaderAt }
  type Source sum { Reader, ReaderAt }
The difference is that Reader and ReaderAt are completely separate types, not type constructors, and that Rust has a shorthand for essentially valueless type constructors, allowing Rust's enums to act both like classic C enums and like sum types. But in Rust, as I understand it, enum variants aren't actually types. In your example, you can't have:

  let r: source::Reader;
Of course, you can do the same thing in Rust, at the cost of readability:

  struct Reader { ... }
  struct ReaderAt { ... }
  enum source { Reader(Reader), ReaderAt(ReaderAt) }
> The proper way to fix this would of course be the same one C# took

It's just too late for Go to do anything here, I think. Zero values permeate the language. For example, consider structs. It's normal to do:

  var f Foo
  if err := json.Unmarshal(b, &f); err != nil {
    ...
  }
It's unfortunate.
Re:Go is boring, and that’s fantastic by masklinn on Friday July 03, 2020 @06:03PM (#23728031)
> My understanding is that there's no real distinction between "sum type" and "union type" as such.

There’s a difference in the ambiguity — or lack thereof — which is the purported reason why go could not have sum types.

> But in Rust, as I understand it, enum variants aren't actually types.

That’s correct. They’re just constructors for values if the enum type.

> It's just too late for Go to do anything here, I think. Zero values permeate the language. For example, consider structs. It's normal to do

It’s not too late for anything. Existing types do not have to change and don’t prevent adding new non-default-able types (which would be transitive).

Those types, with those new guarantees, would not allow for the magical zeroing and zero-extending of existing types but they would not break anything.