You could, but the issue is that now when I'm defining a type I need to think about it's nullable behaviour.
Versus if I instead view nullability as a way of transforming types (aka a functor) that works by reflection; this gives me some parametricity: the behaviour of my function will be the "same" regardless of which generic I slot in (though fields don't play that well with generics... something something row polymorphism something something).
Ill formed thoughts really; what I'm handwaving at is I slightly agree with the anti-complexity crowd that an operator should usually do the same thing, and yet I think it harms terseness and hence often readability and understanding to have non-overloaded boilerplate everywhere (addf64, addu32, addi16...).
Parametricity is a nice compromise for non-primitive ops, imo.
Yeah, there are two ideals I think of in terms of programming languages:
(1) As a simple set of primitive operations that I can use to build up increasingly complex operations and on that level I value "simple". Like the all-virtual method dispatch in Java as compared to whatever it is in C# or C++. In that case I value predictability and users knowing what they're going to get.
(2) As a platform for domain-specific languages such as the tactics described in On Lisp although those tactics apply well to other languages. In that case my desires as an "author of libraries" and "users of libraries" start to diverge. With that hat on I start to think (a) application programs can consist of "islands" with radically different coding styles (say in Java part of the system is comfortable with POJOs but other parts work with dynamically structured data with no schema or a schema defined at runtime) and (b) I'd like to be able to bend the language really far.
From the viewpoint of a programmer who wants to get work and have an impact on the industry I'm usually working in commercially mature languages and finding as much of those values in them as I can.
Versus if I instead view nullability as a way of transforming types (aka a functor) that works by reflection; this gives me some parametricity: the behaviour of my function will be the "same" regardless of which generic I slot in (though fields don't play that well with generics... something something row polymorphism something something).
Ill formed thoughts really; what I'm handwaving at is I slightly agree with the anti-complexity crowd that an operator should usually do the same thing, and yet I think it harms terseness and hence often readability and understanding to have non-overloaded boilerplate everywhere (addf64, addu32, addi16...).
Parametricity is a nice compromise for non-primitive ops, imo.