Completely agnostic problems do exist and modules to solve those can be very strong - but that is a small subset of all the problems we want modules for.
In Python, for example, whenever I'm doing operations on lists, I need to consider every function in isolation - will this break for an empty list (zip), or will it break when given a generator (anything that traverses twice)? If I pass a callback with side effects, how will it behave differently if someone calls it twice?
In a a more rigorous ecosystem, I can instead only worry about edge cases on classes of functions/data types - In Haskell, when doing the same operations, I can generally assume that traversal functions were written with consideration for functor/foldable/traversable laws, and those laws tell me how I can safely compose or swap them out without breaking expectations around those edge cases. Higher Kinded Types let code be constrained to work strictly with those abstractions, so I mostly just need to worry about "does this typecheck" and, very rarely, "is this an unlawful traversal". With things like linear and dependent types entering this mix, library authors can communicate even more subtle expectations at compile time instead of leaving users to try to anticipate them or find them at runtime - when you do need to explicitly consider edge cases, the turnaround time on discovering them is important.
However, databases are cost effective to build and distribute, but implementing that level of rigorous proofs for your e-commerce app is not only generally undesired but often increases the difficulty in reaching profitability and can sink a company. Working on system development isn't limited to academic concerns, if you're guiding project development you have to make really hard calls about correctness vs. cost and I say this as someone who likes to be a perfection and do things the right way whenever possible.
So I don't disagree that careful decisions can scale with abstractions - it isn't the case that it is impossible to build a well designed large system, but it will be expensive and at the end of the day we all (probably?) need to balance cost of investment vs. value of that investment - or are having someone higher up the chain making that decision for us.
However the benefits of sticking with those names and jargon is that it only needs to be explained once. Analogies and metaphors help when you're starting out but you don't need to keep them around. It makes speaking precisely with colleagues in the ecosystem easier.
Proofs are on another level. I've also written proofs and they require much more rigor than you will find in Haskell. It can still be done without a degree but I agree -- not useful for most line-of-business applications.
However the power-to-weight ratio of learning the abstractions available in Haskell is smooth. It takes effort to acquire but it pays off in spades. That's where the "scale" comes from.
Polymorphism combined with composition means that once I know a type implements "Traversal" I can use the entire language of traversals with those data types without knowing anything else about the value I'm working with. The more things that implement traversal the more rich my program becomes.
It's not that you can't do composable software with OOP... it's rather that functional programming is all about composition.