Wow, really? I learned some Haskell on the side a few years ago, and typeclasses were one of my favorite features. They allowed so much expressiveness from such small building blocks. They seemed like a cornerstone of the language.
Highly abstract and general typeclasses for standard mathematical and algebraic concepts are extremely useful and not eschewed. With them you can do genuinely generic programming in a syntactically convenient way. Examples include: Functor, Applicative, Monad, Num, Floating, Integral, MonadState, MonadReader, Profunctor, Contravariant, ...
Typeclasses which are ad hoc, specific, and typically defined on a per project basis, are much more debatable. If you have the concept of "rendering to the screen" and you have typeclass Renderable with a render method then this is really no better than just writing separate functions for each instance of the Renderable. This isn't genuinely generic programming, it's just symbol overloading.
Hey, you're talking about my library Renderable - and I'm totally up to finding a more idiomatic way to express the problem. It just so happened that type classes were the easiest way to do that.
Ha, sorry, didn't mean to make it sound like I was talking about anything in particular! I just made up that example on the spot. A "Renderable" thing fits into a common pattern where you see typeclasses used in this way.
Ahh - I thought you may have read my articles on HN or Reddit - how self centered of me :)
Yes, there's no 'Renderable' typeclass but there are 'Primitive's. There are no laws that the 'Primitive' typeclass instances must obey but there are associated types that need to be satisfied. I tried to write this without a typeclass and I just couldn't get it to check, so I turned to TypeFamilies to encode the relation ship between types. I'd love to make it more idiomatic though!