For example, how would you write a function that answers the mean value of an array of numbers? You could define Array.Length to be of type NonNegativeInteger, but that still includes 0. Alternatively, you'd have to define a NonEmptyArray type that excludes arrays of length 0, but that seems less than useful.
The thing is that, instead of redefining everything yourself, you could use a library that provides you with a set of predicates to compose and build the refinement you need. There are also much sophisticated ways to do this, like Liquid Haskell.
I think the usefulness of a specific NonEmptyArray type is controversial, and I would say such types could be extremely useful. AFAIK there have been discussions if Haskell's Prelude (part of the standard library providing a name space for convenient functions and types, similar to the functions you get in e.g. Python like map, zip, filter, range, etc.) should be more save by not advocating too generic types and functions like the standard `map`, `head` and `tail` implementations.
Functions like `head` and `tail` can be seen as problematic as they can fail and cause runtime errors (the head and tail of an empty list cause a runtime error), but I do not think they already changed that (or if it's even a topic of discussion at the moment).
It's a little bit a matter of taste. Think about Unix' "head" program that by default prints maximal 10 lines of a file. How should we deal with the following?
$ touch empty.txt
$ head -n1 empty.txt
Currently this works - you do not get output and $? == 0, but one could also say "head" should panic here.You can look at the NaN value as an implementation of Option / Maybe, where it means None. It even behaves like it should, short-circuiting any normal operations with it to also produce NaN. Too bad Fortran and C lack sum types to surface that properly on the type level.
NaNs should not be scary.
I prefer an exception because I'd rather have my code fail fast, and immediately point me close to the source of the bug, rather than letting a NaN or Infinity propagate through my code base and cause some harder-to-debug problems down the line.
That's the main thing I don't like about JavaScript. 1/0 is Infinity, Math.acos(2) is NaN, Object().foo is undefined, etc. I find myself wasting a lot of debugging time just figuring out where those (usually expected) values came from originally.
Doesn't it depend on the product in question? In some cases, you want to fail fast and loud. In others, you want to recover at all costs. Sometimes a single calculation going 1/0 means the whole program is failing. Sometimes it's a completely ignorable, minor error, not even worth checking for.
Can we please not have a "default" way of handling errors? None fit all.
Well language designers have to make the choice. I think overall, the best approach is Python's behavior, where both 1/0 and 1.0/0.0 trigger a ZeroDivisionError.
Of course. I meant, no "default" that we would consider the "right way" for all the languages.
My contention is that all NaN-resulting operations (Inf * 0, sqrt(-), e.g.) should halt the program instead of propagating a silent, dud value. When you reach them, it means usually there is something wrong with your algorithm (or less commonly, your data) and it is better to know that sooner than later.