2) What if, in client code, I want to make a value of type “foo option”, completely unaware that foo's underlying implementation is “bar option”? Is it still a code smell? Do I have to know what abstract types defined by other people are implemented as options, so that I don't wrap them in options of my own?
3) Meh.
4) My pattern matching is completely safe. OTOH, with your proposal, you can't safely unwrap those nested structs of nullable pointers in a single step, because you need to unwrap the first layer just to check whether the second layer is safe to unwrap.
---
2) The problem exists whether there exist non-disjoint types or not. Oftentimes I do want to use nested types, because that's the way the data is naturally structured, i.e., that's what shortens the description of the operations that act on the data. Flattening the nested type into a single sum with 4 constructors would merely impose on myself of undoing the flattening every time I want to operate on this sum.
3) It's abstraction for the sake of making code easier to reuse and verify.