- Easy wrapping to create new types: Ever switched the arguments of `mv` in your terminal (strings)? Read the User ID as an account balance (ints)? You can distinguish these statically, and it's easy to do so. (You can of course write a wrapper class in C++ around Int as well a la "class OtherInt { int value; int get(); set(int i) }", but how often do you do that?
- No IO in a type? It cannot do IO. Has "Monad" in the type? It can do Monadic stuff, but no operations specific to any Monad instance (such as Maybe, IO, ...).
- Types are forced documentation. Don't get me wrong, no documentation is as awful in Haskell as it is anywhere else. However, even without any ordinary comment, a type can give away a lot of what a function does; maybe even more importantly, it tells you what it cannot do. If you see something of type `(a -> b) -> (a -> a)`, you know that the first argument cannot possibly be used - it has to be a dummy parameter.