NULL makes little sense from first principles. Either get rid of it, or allow nulls (and logically any other union) by supporting union types. It is quite arbitrary to allow a type that makes sense (string, int) etc. and then also allow nulls so you allow INT | NULL union but no other unions. So you have this multi-purpose "other value" whose meaning is inferred by the application. I guess they were added as a pragma…
The problem is the way it's handled in many programming languages, where it can blend so easily with legitimate value and blow the whole program off at execution time.
It's a practical problem, not a theoretical one.
And it's not the same as union types. The division of two numbers always returns a number, and nothing else, it's just that, for some values, it's not defined.