There's cargo culting on both sides of the question.
Because someone heard pg say he's not overly fond of overly OO code (which he has said in the arc design document), or some other well-known thought leader on programming (like Yegge), they then form a particular dislike of all OO code and even the idea of OO, itself. It's not rational or very fully formed for most of the folks who hate OO. Likewise, there are folks coming from (maybe?) a Java or C++ background, who feel that strict OO is the only sane way to approach designing a program.
I'm not going to try to give examples of good or bad code in either category...but, will point out that Haskell is not an OO language (in the Grady Booch sense of OO, though you can encapsulate methods in data because it has first class functions), but there's an awful lot of beautiful and correct Haskell code out there. Likewise many other functional, Lisp, and ML-derived languages. OO design can obscure meaning, but there's no reason to get reactionary about it. It's one useful tool; it certainly works great for UIs and some types of API.
I'd like to try pushing the Haskell-is-an-OO-language bit a little further. I think Haskell98 is lacking, but with existential types you can model process entities in a way that I think is often underappreciated. As an off-the-cuff example, consider a counter. A simple approximation might be to say that (Int, Int -> Int) models a counter because it models the state of one, but it also fixes the implementation and fails to encapsulate.
But we can do better with existential types
data Counter =
forall x . Counter { _step :: x -> x
, _view :: x -> Int
, _state :: x
}
step :: Counter -> Counter
step c@(Counter {..}) = c { state = _step _state }
view :: Counter -> Int
view (Counter {..}) = _view _state
At this point, we're passing around the internal state as "some type x" which can never be inspected, achieving encapsulation. We can create general functions that manipulate Counters
We also now must start thinking of our "objects" as entities because we cannot compare their internal state for equality (unless we give it an Eq constraint). This begins to quickly demand we keep some notion of state as we need to model "pointer equality" pretty quickly.
We can even do HAS A subtyping. Lenses make this very powerful.
data TwoCounters =
forall x . TwoCounters { _c1 :: Lens' x Counter
, _c2 :: Lens' x Counter
, _state :: x
}
There's no doubt that this is an uncommon technique in Haskell, but it's worth stating that there are a LOT of similarities between codata modeling like this and typeclasses.
Finally, I began to follow a lot of this due to a middling popular library `folds` [1] which describes very generic ways of traversing data structures and accumulating some kind of result state. Basically all of the types dealt with in this library (L1, L1', M1, R1, L, L', M, R) are existentially quantified codata "objects" like I described above. This makes for very general code.
By the way, for those who aren't familiar with Lenses, it's not a bad thing to think of them as getter/setter pairs (which should be a little unsurprising at this point). They're first class, more principled, and more generalizable than your typical getter/setter pair... but my use of them here is far from unintentional.
Because someone heard pg say he's not overly fond of overly OO code (which he has said in the arc design document), or some other well-known thought leader on programming (like Yegge), they then form a particular dislike of all OO code and even the idea of OO, itself. It's not rational or very fully formed for most of the folks who hate OO. Likewise, there are folks coming from (maybe?) a Java or C++ background, who feel that strict OO is the only sane way to approach designing a program.
I'm not going to try to give examples of good or bad code in either category...but, will point out that Haskell is not an OO language (in the Grady Booch sense of OO, though you can encapsulate methods in data because it has first class functions), but there's an awful lot of beautiful and correct Haskell code out there. Likewise many other functional, Lisp, and ML-derived languages. OO design can obscure meaning, but there's no reason to get reactionary about it. It's one useful tool; it certainly works great for UIs and some types of API.