Earlier quoted context omitted.
I think formalization and abstraction are two different things, and you conflate them in your comment. Formalization, in my view, is about "knowing what you are talking about". So you have a perfectly defined set of basic operations on the concepts you use, and you know what you can do with them and what happens if you do; you cannot cheat by making stuff up as you go along. On the other hand, abstraction deals with…
I was using abstraction in the sense of "lambda abstraction", like a formally specified function with parameters. Well, I had to remind myself what the actual design patterns "movement" is, and I get the impression that it's a dead movement with no development since the classic book and a very limited influence. It seems that maybe the bigger problem is that there is no "theory of software" aside from a few interesti…
I think having very strong foundations is very comforting, and the separation of side effects (and introducing them into the type system) has important consequences for composability. But it is still hard and work in progress.
One of the more subtle criticism I have of the classic design patterns is that they often rely on interfaces as descriptions of objects (in the general sense). But it is a very weak description, and indeed, the most useful type classes (which is comparable to interface) in Haskell actually also have laws (not expressible in the type system, for better or worse) that describe behavior. This was a point made by Erik Meijer, that really, you want to describe the objects (that your abstractions can work with) with the laws governing them, not interfaces.
So yes, I think the type classes with laws that are commonly used in Haskell (which is actually pretty much application of mathematical concepts) are the way forward, because they are both better defined and more fruitful (thanks to being explicit about laws) than design patterns.
In particular, I suspect the whole field of group theory is still waiting to be discovered by programmers; I had this idea of looking at error handling and recovery, or transactional processing, as a group operations within a certain subgroup (of valid system states). So no operation or empty transaction is a neutral element, and recovery from action or transaction rollback are inverse elements in some group. I am not yet clear whether this is helpful or trivial, and I am not really sure how to proceed with it. But Monoid abstractions are already quite used in Haskell, so why not Group ones?