I understand that n4009 was written long time before concepts got merged into C++ draft, but they both landed in C++20. 

I presume nobody wrote proposal because people were busy with other things, but I wonder if there are other reasons?

To be clear what I am asking I will quote relevant part of 2014 paper:

Q10. Instead of overloading erase_if() for each container, should you provide
a single erase_if(Container&, Predicate) function template that's specified
to do the right thing for each container?

A10. Such a general function template could be given user-defined containers.
There aren't any "container traits", so it's impossible to determine whether a
user-defined container is vector-like, list-like, map-like, or something else.
User-defined containers could simply be rejected, but then the general function
template wouldn't be doing anything differently than the set of specific
overloads being proposed here.  Note that an author of a user-defined container
can overload erase_if() for their container in their namespace.


This makes sense in 2014, but reading this now this kind of invites a question of reformulating this in terms of concepts, so it can work for abseil or boost containers. 

I presume big part of work here is determining what erasure api one must demand from a container based on it's category and determining that category, but I would naively assume almost all containers follow same API as their std:: counterparts.

I am aware there are no container concepts in C++20, only range concepts like contiguous_range, etc. so I understand adding them is not a trivial task, but my question still remains.