Yes, it's verbose, but verbosity also adds information that may be useful (although + is probably not a good example for this). With 'easier to understand' I mean that when looking at a bit of code I can tell what it does without having to know much about the context (typing, overloading). I did not mean to say that the code is prettier. Haskell code tends to be very pretty.
It's probably difficult to strike the right balance between too little and too much overloading. Maybe OCaml does not allow enough overloading. For my taste typical Haskell code uses too much. But that's a matter of taste, I suppose.
>when looking at a bit of code I can tell what it does without having to know much about the context
How do type classes make that harder? You either need to understand what "foo" does, or you need to understand what "fooForThisType" does. What's hard about the former?
You need to know the type. I wouldn't want to say that makes reading code "hard", but it means that you need more context in order to understand the code. (Imagine, for example, that you're trying to understand a patch, where not all types are obvious).
You only need more context in order to know where to look to understand the code. If you don't know what foo does, you have to go look at the definition of foo. If foo is obvious or common, then you don't care which instance's version of foo is being called. To a person reading the code, + is + regardless of whether it is adding ints or floats. If you are looking at a patch and don't know what a function does, then you need to go look at the actual code. In which case, the types are now obvious (or can be given to you by the compiler if they are not obvious).
Are there alternative approaches I am not aware of? All I can see is encode the type in the name of the function (fmapList, fmapMaybe, fMapVector, etc), or forcing the functions to all be in separate namespaces and have to qualify them (List.fmap, Maybe.fmap, etc). Both seem much worse than typeclasses.
It's probably difficult to strike the right balance between too little and too much overloading. Maybe OCaml does not allow enough overloading. For my taste typical Haskell code uses too much. But that's a matter of taste, I suppose.