> We can’t perform arithmetic on an Option<int> any more than we could on a List<int>.
Why not? One sensible definition is
Some(x) + Some(y) = Some(x + y)
_ + _ = None()
> In fact, with Dart, we’ve found that most existing code is already statically null safeThis is a very good reason to use union types — lots of programs and lots of people are used to thinking this way, and pulling that out from under their feet wouldn't be very nice.
> Nullable types, since they have no explicit runtime representation, are implicitly flattened.
Yes, flattening things that shouldn't be flattened is the biggest problem with union types. Different people will assign different meanings to null, and it's a real headache when trying to write generic code. Discriminated unions make this a no-brainer.
> With nullable types, since there is no representation difference, you can pass a value of the underlying type directly: takesMaybeInt(3);
That's a very minor difference, but if it's that important, Rust lets you write
fn takesMaybeInt(x: impl Into<Option<i32>>) { ... }