News for hackers. Stuff that matters.
Re:Go is boring, and that’s fantastic by akavi on Thursday July 02, 2020 @09:30AM (#23712874)
Exactly. I don't want sum types becuase they're exciting, I want them because they're the simplest way to communicate to the compiler that "my data can either be this or this and nothing else", so I don't blow off my foot by accidentally making it that.

When I was younger and less jaded, it actually was fun and exciting thinking up ways to hack around language limitations like that. Now it's just frustrating.

Re:Go is boring, and that’s fantastic by frankie_t on Thursday July 02, 2020 @10:08AM (#23713236)
That actually surprises me a lot. I've seen plenty of critique about lacking generics and exceptions, while haven't seen much complaint about ADTs. From my rather dilettante point of view they are neither too complex for "philosophy of simplicity", nor they add much of compile time. It seems to me they even can be implemented as a syntactic sugar on top of type casts. I certainly cannot see them being more complex than generics.
Re:Go is boring, and that’s fantastic by akavi on Thursday July 02, 2020 @10:15AM (#23713310)
Yeah, it's unclear to me why there's not more demand for them either. I think it might that most go users with prior static language experience are coming from Java, where there aren't sum types either.

From my naive perspective, they seem like an easy win, and are 100% more important to me than generics.

Re:Go is boring, and that’s fantastic by estebank on Thursday July 02, 2020 @11:56AM (#23714678)
Adding ADTs on their own is not enough, you need to add pattern matching and generics to unlock their biggest benefits.
Re:Go is boring, and that’s fantastic by ithkuil on Friday July 03, 2020 @03:59AM (#23721988)
Go's type switches could be good enough if there was a way to restrict an interface-like type to be either one of A, B, C types.

    type foo either {
     int
     string
     *bar
      baz
    }
...

     var f foo = ....
     switch v := f.(type) {
       case int:
       // v has type int
       case string:
.....
Re:Go is boring, and that’s fantastic by masklinn on Saturday July 04, 2020 @06:18AM (#23731358)
The problem with this is it's extremely limiting and conflicts with interfaces. So it's not very useful: you can't define enumerations with no associated data, or enumerations with the same associated data types, without the syntactic overhead of explicitly wrapping and unwrapping those types. So you'd end up with

    type thing1 int
    type thing2 int
    type foo either {
        thing1
        thing2
    }

    var f foo = …
    switch v := f.(type) {
        case thing1:
            data = int(v)
        case thing2:
            data = int(v)
        …
and frankly that's a bit gross.

I think `select` would be a better basis for dispatching than switch as it already supports getting data out of stuff, and it better represents the linear top-to-bottom dispatching.

Re:Go is boring, and that’s fantastic by ithkuil on Saturday July 04, 2020 @02:37PM (#23734062)
I'm a bit confused about the example. It seems you care about tagging an integer with a qualifier.

    type foo struct (
      kind Kind
      data int
    }
Then you switch on kind and you use the data

The type switch is useful when you have to consume the actual type, without runtime errors for type conversions

Re:Go is boring, and that’s fantastic by masklinn on Saturday July 04, 2020 @03:38PM (#23734415)
> I'm a bit confused about the example. It seems you care about tagging an integer with a qualifier.

No, I'm pointing out that a proper sum type can (and often does) need that. It doesn't mean those are the only members.

> The type switch is useful when you have to consume the actual type, without runtime errors for type conversions

My point is that the type switch is garbage when multiple variants can have the same associated type.

Re:Go is boring, and that’s fantastic by ithkuil on Saturday July 04, 2020 @05:38PM (#23735079)
I see; that's because I'm this case we'd be fusing the discriminator with the payload.

With destructuring pattern match constructs you'd be binding variables to "inner" members of the sum type.

I do understand that. I'm not so sure it's so important, compared to Just being able to say that a box can contain either A or B or C.

Interfaces are great when you don't care what does a box contain as long as it quacks like a duck.

Sometimes though you need to carry around one out of N types of something and currently all you can do is to use an interface{} and deal with the possibility of a runtime error if somebody breaks the invariant.

Re:Go is boring, and that’s fantastic by masklinn on Sunday July 05, 2020 @04:52AM (#23737426)
> I do understand that. I'm not so sure it's so important

It absolutely is, even more so because of Go's interface. The difficulty of properly discriminating between interfaces extending one another is a reason the FAQ gives for rejecting union types.

> compared to Just being able to say that a box can contain either A or B or C.

I'd argue that this is by far the lesser use case, and furthermore trivially and completely subsumed by the alternative.

> Sometimes though you need to carry around one out of N types of something and currently all you can do is to use an interface{} and deal with the possibility of a runtime error if somebody breaks the invariant.

And sometimes you need to carry around one of N values some of which have overlapping contents and currently all you can do is get bent.

Re:Go is boring, and that’s fantastic by tleb_ on Thursday July 02, 2020 @10:32AM (#23713513)
I believe sum types are not added because they come close in functionality to interfaces, the idea being that if something should be X or Y, you make an interface that X and Y implement.

Edit: true explanation here https://golang.org/doc/faq#variant_types

Re:Go is boring, and that’s fantastic by SmooL on Thursday July 02, 2020 @10:57AM (#23713905)
That's fair from one use, but the other, way more common in Go, is the whole "I'm going to return either an object OR an error". There's no common interface between the two, it's a distinct two options. Because go has no native support for sum types you get all this nonsense where every function returns a tuple of an object and an error, with the implicit assumption (not at all checked by the compiler) is that if the error is nil, then the object is valid. It's awful
Re:Go is boring, and that’s fantastic by AnimalMuppet on Thursday July 02, 2020 @12:23PM (#23714929)
Hmm. Instead of a sum type, it returns (in essence) a product type.
Re:Go is boring, and that’s fantastic by SmooL on Friday July 10, 2020 @10:30AM (#23791793)
Good point; I guess that's really crux of the issue: we use it as a sum Type, but the compiler sees it only as a product Type
Re:Go is boring, and that’s fantastic by karmakaze on Thursday July 02, 2020 @12:01PM (#23714719)
That's not even true in the stdlid--there are some io errors that aren't errors per se and at the same time perform an action and return a value, e.g. short-write.
Re:Go is boring, and that’s fantastic by reificator on Thursday July 02, 2020 @01:03PM (#23715325)
Sure, and in those cases you could continue to return a tuple. In fact having those cases not return a Result<T, E> when everything else does would actually make it more discoverable; right now people assume err means failure.
Re:Go is boring, and that’s fantastic by mumblemumble on Thursday July 02, 2020 @12:45PM (#23715148)
There is some similarity, but it is so agonizingly superficial. At their core, they're for two very different, arguably orthogonal, purposes, and they behave in two very different ways. Sum types are for composing datatypes, and interfaces are for abstracting behaviors.

In practice, that means that there's just not much overlap between their semantics. Sum types let you say, "A Widget is either a Foo or a Bar, but nothing else." Interfaces give you no way to set boundaries like that. They say, "A Widget is anything that declares itself to be a Widget." And then you can declare Widgets Foo and Bar, sure, but anyone else can come along later and create Baz and Bof.

Interfaces, on the other hand, place restrictions on behavior. You say, "A Widget must support these operations," and, if Foo and Bar are Widgets, they must support those operations. Sum types don't let you do that. A sum type Widget with elements Foo and Bar places zero restrictions on what Foo and Bar look like. They could be literally anything.

The question, "What would happen if the elements of a variant type were themselves interfaces?" leaves me wondering if the authors' consideration of variant types consisted of taking a cursory look at Scala, which does (confusingly and hackily) co-opt Java's inheritance mechanisms in its implementation of sum types. Which does lead to some serious language warts. There are plenty of other languages which have both interfaces (or typeclasses) and sum types implemented more independently, though, and it does not typically lead to confusion.

That last paragraph is also somewhat bothersome, and makes me think once again that this response is more of an offhanded dismissal than a considered answer. The full question is essentially, "Why don't you implement this feature that would greatly increase the language's type safety?" and the response is, "Because you don't need it. See, if you just abandon type safety, what you can do is..."

I suspect that the real answer, even if the FAQ authors or the people who designed the language don't realize it, is that generics are practically (if not technically) a precondition for an algebraic type system. You could implement one without generics, but it wouldn't be very useful.

Re:Go is boring, and that’s fantastic by ngrilly on Thursday July 02, 2020 @04:18PM (#23717556)
There is not a lot of critics about the lack of ADTs because most people have never been exposed to them and don’t even know what they are and the concepts of product and sum types. Generics are much more common.
Re:Go is boring, and that’s fantastic by entha_saava on Friday July 03, 2020 @01:34AM (#23721296)
They gave the reason for not including tagged unions that they overlap in confusing ways with interfaces. Not that the reasoning is correct or not. It was their goal to make the language dead simple.

Now with the new generics proposal, it seems they have hacked up some crude closed interface types, which are something like union types. :/

Re:Go is boring, and that’s fantastic by ithkuil on Friday July 03, 2020 @04:03AM (#23722016)
Can you make an example of how it would be confused with interfaces in weird ways?
Re:Go is boring, and that’s fantastic by entha_saava on Friday July 03, 2020 @05:42AM (#23722557)
Maybe something like a union of struct type T and interface type I, but T also satisfies I. Then you have to specify some extra things / add features to keep it symmetric and being able to construct it both ways equally easily. GO Authors have a primary goal of

Secondly, they think interfaces cover many of the need of variant types and they don't want some non-orthogonal feature.

Re:Go is boring, and that’s fantastic by ithkuil on Friday July 03, 2020 @10:41AM (#23724442)
imagine an interface{} that can be annotated to say "you can only assign values ofItypes A, B and C to it. E.g. interface(A,B,C){}

Since it's an interface{} it has no behaviour, the only thing you can do is a type assert / type switch.

By extension, you could add some methods: interface(A,B,C){Foo(bool) int} This fails statically unless A, B, and C implement said interface. If they do, then this interface has exactly the same semantics as the normal Go interfaces, except that only types A, B and C can be assigned to it (and not type D even if it implements Foo(bool) int

Re:Go is boring, and that’s fantastic by mrkeen on Thursday July 02, 2020 @02:10PM (#23716208)
I think it's just down to population sizes. There's a mass of people who already have (non-higher-kinded) generics and exceptions in a language they already know, so they know what they're missing. Far few people have access to ADTs.
Re:Go is boring, and that’s fantastic by LandR on Thursday July 02, 2020 @05:30PM (#23718282)
This is almost blub by definition.
Re:Go is boring, and that’s fantastic by dorian-graph on Thursday July 02, 2020 @01:15PM (#23715490)
If anything, nil checking in Go makes it quite exciting (will I get a nil pointer error somewhere? Who knows!). Sum types would make this quite boring though.
Re:Go is boring, and that’s fantastic by masklinn on Thursday July 02, 2020 @03:07PM (#23716808)
> If anything, nil checking in Go makes it quite exciting (will I get a nil pointer error somewhere? Who knows!).

The most exciting part is finding that something is not nil but is actually nil. Great surprise, thanks typed nils!

Re:Go is boring, and that’s fantastic by erik_seaberg on Thursday July 02, 2020 @05:10PM (#23718111)
It's the only language I've ever seen that tries to dispatch on what type of object you don't have. Very zen.