It's funny you should mention that--it seems Haskell usually gets accused of being too abstract. In Haskell, it's actually common to write very abstract code.
In fact, I think that is one reason why Haskell is tricky to pick up at first. OO "abstraction" is never that abstract--you can always tie it down to some concrete thing or idea. An iterable is obviously something you can iterate over, and that's about as abstract as you get.
Haskell, instead, finds its core abstractions in math. It uses ideas from abstract algebra and category theory that are more general than anything I've seen in OO. The core abstractions like the infamous monads, functors, monoids, arrows and so on are not easy to tie down to anything concrete at all.
For example, the standard functions that work on monads (like foldM) can work on a dizzying array of different types: functions, lists, nullables, continuations, errors, parsers, ASTs. Any given function like this does the same thing parametrized by the behavior of the type in question: so foldM always does a fold, but the exact behavior depends on the exact monad being used to do the folding. And there is no obvious relationship between the different behaviors that can be modelled this way.
In short: Haskell uses ideas from math to get very abstract code, for better or worse. These mathematical concepts can model a gigantic amount of different things which, intuitively, may not seem related at first.
In fact, I think that is one reason why Haskell is tricky to pick up at first. OO "abstraction" is never that abstract--you can always tie it down to some concrete thing or idea. An iterable is obviously something you can iterate over, and that's about as abstract as you get.
Haskell, instead, finds its core abstractions in math. It uses ideas from abstract algebra and category theory that are more general than anything I've seen in OO. The core abstractions like the infamous monads, functors, monoids, arrows and so on are not easy to tie down to anything concrete at all.
For example, the standard functions that work on monads (like foldM) can work on a dizzying array of different types: functions, lists, nullables, continuations, errors, parsers, ASTs. Any given function like this does the same thing parametrized by the behavior of the type in question: so foldM always does a fold, but the exact behavior depends on the exact monad being used to do the folding. And there is no obvious relationship between the different behaviors that can be modelled this way.
In short: Haskell uses ideas from math to get very abstract code, for better or worse. These mathematical concepts can model a gigantic amount of different things which, intuitively, may not seem related at first.