Just had the realisation that as long as a language has parametric polymorphism and higher order functions, it implicitly also has a mechanism for defining an abstraction independently of its implementation (e.g. interfaces, protocols, etc), by defining lenses/prisms. These allow code module to depend on being able to get/set part of a large data structure without having to know it’s internal structure, simply by being passed lenses over the parts, and only parts, that it depends upon.