News for hackers. Stuff that matters.
Re:Flutter 2 by oblio on Wednesday March 03, 2021 @04:01PM (#26334479)
Let's say you get a JSON API that sometimes returns a list, sometimes returns an object. How do you model that in Dart?
Re:Flutter 2 by munificent on Wednesday March 03, 2021 @09:45PM (#26337991)
Yes, union types are really nice for data like that.

But, in practice, a language's type system tends to optimize for the data structures that are idiomatic in the language. TypeScript is a heavily structural type system because idiomatic JavaScript often throws together unrelated types in this way (which makes sense when you're coming from dynamic types).

In a language that is built more strongly on objects and static types, it's less common to see APIs that "return one of these, or one of these, or on Sunday one of these things". So there is relatively less use for union types.

In other words, because people express unions at runtime less frequently in Dart (and other languages like Java and C#), there's less value in supporting them statically. Still some, definitely, but I don't think it's as critical of an omission as you might expect coming from TS/JS.

Re:Flutter 2 by c-cube on Thursday March 04, 2021 @01:53AM (#26339441)
People build less unions because these languages fail them. Just add sum types or something similar, it's a disgrace to not have them in 2021. Static typing goes wonderfully well with them, allowing for exhaustiveness checks and all that.

The "people use fewer unions in Java" argument is like saying people used fewer lambdas in Java 1.6. Build it, and they will use it.

Re:Flutter 2 by munificent on Thursday March 04, 2021 @01:24PM (#26346113)
> Just add sum types or something similar

I think you're confusing union types and sum types, which are very distinct features. SML, Haskell, and Rust don't have union types.

OOP languages can model sum types already. It's mostly a question of how much the surface syntax encourages that style.

Re:Flutter 2 by c-cube on Thursday March 04, 2021 @01:39PM (#26346319)
I'm not confusing them :-)

I think _closed_ union types (the syntax `a | b | c`) are almost as good as sum types, since they bring exhaustiveness checking to the mix. They also act as documentation. Crystal is a good example of a language leveraging this feature.

The OO model of just subclassing a common class is quite poor by itself. Scala and Kotlin have a 'sealed' modifier to at least recover the exhaustiveness check. Both also have ways of safely doing the case switch on the object's class and simultaneously downcasting (Java too with its recent `match` construct, afaik). Does Dart have anything like that?

Re:Flutter 2 by munificent on Thursday March 04, 2021 @05:03PM (#26349059)
> The OO model of just subclassing a common class is quite poor by itself. Scala and Kotlin have a 'sealed' modifier to at least recover the exhaustiveness check.

The natural OOP way to model an operation that must exhaustively be supported by a set of types is by making it an abstract method on a shared superclass. For problems where it's natural to keep the operations textually near each type, that works great.

Otherwise, yes, you'd ideally have some notion of a sealed family of types so that you can do case analysis with exhaustiveness checking. That lets you ensure all operations are covered when you program either in OOP or FP style.

Something I find odd is that FP folks often criticize OOP languages for not supporting exhaustiveness checking, but I rarely hear them admit that most FP languages don't have support for the other style that OOP does well, which is abstract methods.

Re:Flutter 2 by c-cube on Thursday March 04, 2021 @05:12PM (#26349177)
As far as typed FP languages go:

- Scala has the whole OOP stuff - F# as well - SML: you probably need to do it by hand, with a record of closures, or something like that. It's ugly but it works. - OCaml has objects (it's in the name), first-class modules, or records-of-functions; all of which can replace abstract methods successfully. - Haskell can rely on typeclasses to do the virtual dispatch, I think. Not an expert on that.

So I'd say it might not be as ergonomic, but the capability is still 100% there.

Re:Flutter 2 by oblio on Thursday March 04, 2021 @02:35AM (#26339725)
What's the de facto web data interchange language these days? Used by every programming language out there, every language has a library to load it?
Re:Flutter 2 by okamiueru on Wednesday March 03, 2021 @04:14PM (#26334639)
You could create an abstract class for the base response, then implement this abstract class for the two cases one where it has a list member, and one where it contains the object. Then, using the return value with something like `if (response is listLike) { }` the IDE already knows that you are scoped to having only the list like properties, and you'd get the full help of the language. Something like that, I suppose.
Re:Flutter 2 by oblio on Wednesday March 03, 2021 @04:49PM (#26335144)
Versus a sort of:

my_type = my_list | my_object

?

You can see why this is better :-)

Re:Flutter 2 by mixmastamyk on Thursday March 04, 2021 @12:31AM (#26339007)
I'd always return a list. Makes the client code simpler.
Re:Flutter 2 by oblio on Thursday March 04, 2021 @01:16AM (#26339234)
You would. But not every input comes from you :-)
Re:Flutter 2 by okamiueru on Wednesday March 03, 2021 @05:22PM (#26335584)
All I can say is that it is certainly neat :)