Apologies for length, but it’s a big topic and I want to give a high-level view of the whole area. Here are the essential points:
Haskell’s type system is pretty flexible and mostly unobtrusive (unlike some static systems).
A good type system is a powerful design language, too.
We can also work with types in a “type-driven development” style.
Parametric polymorphism is about using the same code for everything.
Interfaces provide clean overloading and encourage and support approaches like DCI.
Often Haskell feels like a dynamically typed language, though with a good safety net in reserve.
Haskell has its limits, but the cost-benefit trade-off is probably in our favor.
There are several options beyond Haskell, such as dependent types. ...