>Strict type system allows for a maximum number of programming errors to be caught at compile time.
I keep hearing this statement but others would argue that programming
errors caught at compile time only form a minor subset of all errors
caught.
So, in functional programming languages with a strict type system,
e.g. Haskell, do typing errors from a larger subset of all programming
errors.
Yes. You can usually write much the same program with and without static types. The difference will be that in the dynamic typing/untyped setting you'll get the errors at runtime, and in the statically typed setting you'll get (many of) the errors at compile time. You can express a lot of invariants with types once you become familiar with their usage. For instance you can make a 2-3 tree in Haskell where the types enforce the fact that the tree is balanced. You can implement the same code in Scheme or another dynamically typed language, but the result will lack that extra guarantee. Nothing says that your insert operation drops the node in the right place, etc, but at last you know you are safe from one class of bugs.
Types effectively prove lots of little boring theorems about your code as you program. Inconsistent code will often cause these sorts of little proofs to fail.
One thing that thinking about types helps you to do is to figure out if given the types if the choice of implementation is more-or-less unique. For instance given the type for fmap, and the extra law(s) you need to satisfy, you really only have one correct implementation option. ;)
So not only do you get benefit from the compiler giving you errors rather than finding out later when your runtime system blows up in production, but the types help inform you as to what the shape of a correct implementation should be.
-Edward Kmett