Most statically typed programs/systems these days (Java, C#, even C++ if you wish) these days, use DI via IoC containers as the mechanism for constructing objects and choosing which code to run. You can even do it with dynamic languages like JS/Python if you wish, though many argue it being dynamic means you don't need to use a container - which is pretty true.<p>This approach is equivalent to a family of functions (with side effects), one family per class, each with N(c) + N(m) arguments, where N(c) is the number of constructor arguments, and N(m) is the number of method arguments. Upon object construction, these families are partially applied to construct a new family of functions that contain only N(m) arguments. You can think of a constructor as a functor, that returns a number partially applied functions - the methods on the classes.<p>This is how I actually think of my OO programs these days. I also make liberal use of the actual functional tools made available to me. For instance, my bread and butter is C#, and LINQ heavily promotes a purely functional style when manipulating collections of data, though side effects are possible.<p>At a system level, I also tend to think of my data pipelines as functional transformations as well - their being written as an OO program is of little actual consequence.