>Other than type-safe heterogenous lists(which is only true if you hold static type systems to a much higher standard of type-safety than dynamic type systems), what sorts of things do a type system with type classes, algebraic data types, and higher order functions prevent doing?
Automatic serializing and deserializing of objects. I wrote the RJson library for Haskell to do this for JSON, but there is no way I would ever write anything like that in Haskell again. Using a statically typed language makes it necessary to use horribly complicated types and (in the case of RJson at least) to lose the guarantee that the program's types are decidable. Also, you tend to find that as the type system grows more sophisticated than basic Haskell 98, there is a much greater likelihood of incorrect programs type-checking correctly, so this becomes a less useful means of preventing errors. In writing RJson, I frequently had to determine the correct types for functions by trial and error -- it kinda defeats the purpose of strong typing when a function's type is harder to understand than the function itself.
In a language like Python or Lisp, with decent reflective capabilities, writing the equivalent library would be a whole ton easier.
Automatic serializing and deserializing of objects. I wrote the RJson library for Haskell to do this for JSON, but there is no way I would ever write anything like that in Haskell again. Using a statically typed language makes it necessary to use horribly complicated types and (in the case of RJson at least) to lose the guarantee that the program's types are decidable. Also, you tend to find that as the type system grows more sophisticated than basic Haskell 98, there is a much greater likelihood of incorrect programs type-checking correctly, so this becomes a less useful means of preventing errors. In writing RJson, I frequently had to determine the correct types for functions by trial and error -- it kinda defeats the purpose of strong typing when a function's type is harder to understand than the function itself.
In a language like Python or Lisp, with decent reflective capabilities, writing the equivalent library would be a whole ton easier.