<strong>In terms that an OOP programmer would understand (without any functional programming background), what is a monad?</strong>
In terms that an OOP programmer would understand (without any functional programming background), what is a monad?
What problem does it solve and what are the most common places it's used?
To clarify the kind of understanding I was looking for, let's say you were converting an FP application that had monads into an OOP application. What would you do to port the responsibilities of the monads to the OOP app?
Object-oriented programming is a programming paradigm based on the concept of "objects", which can contain data, in the form of fields, and code, in the form of procedures.
Originally published by Eric Elliott at https://medium.com/
The functional and imperative programming paradigms we use today were first explored mathematically in the 1930s with lambda calculus and the Turing machine, which are alternative formulations of universal computation (formalized systems which can perform general computation). The Church Turing Thesis showed that lambda calculus and Turing machines are functionally equivalent — that anything that can be computed using a Turing machine can be computed using lambda calculus, and vice versa.
Note: There is a common misconception that Turing machines can compute anything computable. There are classes of problems (e.g., the halting problem) that can be computable for some cases, but are not generally computable for all cases using Turing machines. When I use the word “computable” in this text, I mean “computable by a Turing machine”.
Lambda calculus represents a top-down, function application approach to computation, while the ticker tape/register machine formulation of the Turing machine represents a bottom-up, imperative (step-by-step) approach to computation.
Low level languages like machine code and assembly appeared in the 1940s, and by the end of the 1950s, the first popular high-level languages appeared. Lisp dialects are still in common use today, including Clojure, Scheme, AutoLISP, etc. FORTRAN and COBOL both appeared in the 1950s and are examples of imperative high-level languages still in use today, though C-family languages have replaced both COBOL and FORTRAN for most applications.
Both imperative programming and functional programming have their roots in the mathematics of computation theory, predating digital computers. “Object-Oriented Programming” (OOP) was coined by Alan Kay circa 1966 or 1967 while he was at grad school.
Note: The TX-2 at MIT Lincoln Laboratory was one of the early uses of a graphical computer monitor employing direct screen interaction using a light pen. The EDSAC, which was operational between 1948–1958 could display graphics on a screen. The Whirlwind at MIT had a working oscilloscope display in 1949. The project’s motivation was to create a general flight simulator capable of simulating instrument feedback for multiple aircraft. That led to the development of the SAGE computing system. The TX-2 was a test computer for SAGE.
The first programming language widely recognized as “object oriented” was Simula, specified in 1965. Like Sketchpad, Simula featured objects, and eventually introduced classes, class inheritance, subclasses, and virtual methods.
“I made up the term ‘object-oriented’, and I can tell you I didn’t have C++ in mind.” ~ Alan Kay, OOPSLA ‘97
Alan Kay coined the term “object oriented programming” at grad school in 1966 or 1967. The big idea was to use encapsulated mini-computers in software which communicated via message passing rather than direct data sharing — to stop breaking down programs into separate “data structures” and “procedures”.
“The basic principal of recursive design is to make the parts have the same power as the whole.” ~ Bob Barton, the main designer of the B5000, a mainframe optimized to run Algol-60.
Smalltalk was developed by Alan Kay, Dan Ingalls, Adele Goldberg, and others at Xerox PARC. Smalltalk was more object-oriented than Simula — everything in Smalltalk is an object, including classes, integers, and blocks (closures). The original Smalltalk-72 did not feature subclassing. That was introduced in Smalltalk-76 by Dan Ingalls.
While Smalltalk supported classes and eventually subclassing, Smalltalk was not about classes or subclassing things. It was a functional language inspired by Lisp as well as Simula. Alan Kay considers the industry’s focus on subclassing to be a distraction from the true benefits of object oriented programming.
“I’m sorry that I long ago coined the term “objects” for this topic because it gets many people to focus on the lesser idea. The big idea is messaging.”
~ Alan Kay
In a 2003 email exchange, Alan Kay clarified what he meant when he called Smalltalk “object-oriented”:
“OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.”
~ Alan Kay
In other words, according to Alan Kay, the essential ingredients of OOP are:
Notably, inheritance and subclass polymorphism were NOT considered essential ingredients of OOP by Alan Kay, the man who coined the term and brought OOP to the masses.The Essence of OOP
The combination of message passing and encapsulation serve some important purposes:
These ideas were inspired by biological cells and/or individual computers on a network via Alan Kay’s background in biology and influence from the design of Arpanet (an early version of the internet). Even that early on, Alan Kay imagined software running on a giant, distributed computer (the internet), where individual computers acted like biological cells, operating independently on their own isolated state, and communicating via message passing.
“I realized that the cell/whole-computer metaphor would get rid of data[…]”
~ Alan Kay
By “get rid of data”, Alan Kay was surely aware of shared mutable state problems and tight coupling caused by shared data — common themes today.
But in the late 1960s, ARPA programmers were frustrated by the need to choose a data model representation for their programs in advance of building software. Procedures that were too tightly coupled to particular data structures were not resilient to change. They wanted a more homogenous treatment of data.
“[…] the whole point of OOP is not to have to worry about what is inside an object. Objects made on different machines and with different languages should be able to talk to each other […]” ~ Alan Kay
Objects can abstract away and hide data structure implementations. The internal implementation of an object could change without breaking other parts of the software system. In fact, with extreme late binding, an entirely different computer system could take over the responsibilities of an object, and the software could keep working. Objects, meanwhile, could expose a standard interface that works with whatever data structure the object happened to use internally. The same interface could work with a linked list, a tree, a stream, and so on.
Alan Kay also saw objects as algebraic structures, which make certain mathematically provable guarantees about their behaviors:
“My math background made me realize that each object could have several algebras associated with it, and there could be families of these, and that these would be very very useful.”
~ Alan Kay
This has proven to be true, and forms the basis for objects such as promises and lenses, both inspired by category theory.
The algebraic nature of Alan Kay’s vision for objects would allow objects to afford formal verifications, deterministic behavior, and improved testability, because algebras are essentially operations which obey a few rules in the form of equations.
In programmer lingo, algebras are like abstractions made up of functions (operations) accompanied by specific laws enforced by unit tests those functions must pass (axioms/equations).
Those ideas were forgotten for decades in most C-family OO languages, including C++, Java, C#, etc., but they’re beginning to find their way back into recent versions of most widely used OO languages.
You might say the programming world is rediscovering the benefits of functional programming and reasoned thought in the context of OO languages.
What is essential to OOP (according to Alan Kay)?
What is non-essential?
If your background is Java or C#, you may be thinking static types and Polymorphism are essential ingredients, but Alan Kay preferred dealing with generic behaviors in algebraic form. For example, from Haskell:
fmap :: (a -> b) -> f a -> f b
// isEven = Number => Boolean const isEven = n => n % 2 === 0;const nums = [1, 2, 3, 4, 5, 6];// map takes a function `a => b` and an array of `a`s (via `this`) // and returns an array of `b`s. // in this case, `a` is `Number` and `b` is `Boolean` const results = nums.map(isEven);console.log(results); // [false, true, false, true, false, true]
The .map() method is generic in the sense that a and b can be any type, and .map() handles it just fine because arrays are data structures that implement the algebraic functor laws. The types don't matter to .map() because it doesn't try to manipulate them directly, instead applying a function that expects and returns the correct types for the application.
// matches = a => Boolean // here, `a` can be any comparable type const matches = control => input => input === control;const strings = ['foo', 'bar', 'baz'];const results = strings.map(matches('bar'));console.log(results); // [false, true, false]
This generic type relationship is difficult to express correctly and thoroughly in a language like TypeScript, but was pretty easy to express in Haskell’s Hindley Milner types with support for higher kinded types (types of types).
Most type systems have been too restrictive to allow for free expression of dynamic and functional ideas, such as function composition, free object composition, runtime object extension, combinators, lenses, etc. In other words, static types frequently make it harder to write composable software.
If your type system is too restrictive (e.g., TypeScript, Java), you’re forced to write more convoluted code to accomplish the same goals. That doesn’t mean static types are a bad idea, or that all static type implementations are equally restrictive. I have encountered far fewer problems with Haskell’s type system.
If you’re a fan of static types and you don’t mind the restrictions, more power to you, but if you find some of the advice in this text difficult because it’s hard to type composed functions and composite algebraic structures, blame the type system, not the ideas. People love the comfort of their SUVs, but nobody complains that they don’t let you fly. For that, you need a vehicle with more degrees of freedom.
If restrictions make your code simpler, great! But if restrictions force you to write more complicated code, perhaps the restrictions are wrong.What is an Object?
Our current idea of an object is simply a composite data structure, and does not require anything more to be considered an object. But programming using these kinds of objects does not make your code “object-oriented” any more than programming with functions makes your code “functional”.OOP is not Real OOP Anymore
Real OOP means:
Most component behaviors can be specified generically using algebraic data structures. Inheritance is not needed here. Components can reuse behaviors from shared functions and modular imports without sharing their data.
Is it coincidence that mops are used to clean up messes?What Good MOP Looks Like
In most modern software, there is some UI responsible for managing user interactions, some code managing application state (user data), and code managing system or network I/O.
Each of those systems may require long-lived processes, such as event listeners, state to keep track of things like the network connection, ui element status, and the application state itself.
Good MOP means that instead of all of these systems reaching out and directly manipulating each other’s state, the system communicates with other components via message dispatch. When the user clicks on a save button, a "SAVE" message might get dispatched, which an application state component might interpret and relay to a state update handler (such as a pure reducer function). Perhaps after the state has been updated, the state component might dispatch a "STATE_UPDATED" message to a UI component, which in turn will interpret the state, reconcile what parts of the UI need to be updated, and relay the updated state to the subcomponents that handle those parts of the UI.
Meanwhile, the network connection component might be monitoring the user’s connection to another machine on the network, listening for messages, and dispatching updated state representations to save data on a remote machine. It’s internally keeping track of a network heartbeat timer, whether the connection is currently online or offline, and so on.
These systems don’t need to know about the details of the other parts of the system. Only about their individual, modular concerns. The system components are decomposable and recomposable. They implement standardized interfaces so that they are able to interoperate. As long as the interface is satisfied, you could substitute replacements which may do the same thing in different ways, or completely different things with the same messages. You may even do so at runtime, and everything would keep working properly.
Components of the same software system may not even need to be located on the same machine. The system could be decentralized. The network storage might shard the data across a decentralized storage system like IPFS, so that the user is not reliant on the health of any particular machine to ensure their data is safely backed up, and safe from hackers who might want to steal it.
OOP was partially inspired by Arpanet, and one of the goals of Arpanet was to build a decentralized network that could be resilient to attacks like atomic bombs. According to director of DARPA during Arpanet development, Stephen J. Lukasik (“Why the Arpanet Was Built”):
“The goal was to exploit new computer technologies to meet the needs of military command and control against nuclear threats, achieve survivable control of US nuclear forces, and improve military tactical and management decision making.”
Note: The primary impetus of Arpanet was convenience rather than nuclear threat, and its obvious defense advantages emerged later. ARPA was using three separate computer terminals to communicate with three separate computer research projects. Bob Taylor wanted a single computer network to connect each project with the others.
A good MOP system might share the internet’s robustness using components that are hot-swappable while the application is running. It could continue to work if the user is on a cell phone and they go offline because they entered a tunnel. It could continue to function if a hurricane knocks out the power to one of the data centers where servers are located.
It’s time for the software world to let go of the failed class inheritance experiment, and embrace the math and science principles that originally defined the spirit of OOP.
It’s time for us to start building more flexible, more resilient, better-composed software, with MOP and functional programming working in harmony.
Note: The MOP acronym is already used to describe “monitoring-oriented programming” and its unlikely OOP is going to go away quietly.
Don’t be upset if MOP doesn’t catch on as programming lingo.
Do MOP up your OOPs.
Thanks for reading ❤
If you liked this post, share it with all of your programming buddies!
Learn/Brush up Object Oriented Programming(OOP) skills using Java Programming Language and apply them in real time
Learn/Brush up Object Oriented Programming(OOP) skills using Java Programming Language and apply them in real time
This video is absolutely apt for you if you are already familiar with programming foundations and looking to learn or brush up Object Oriented Programming features, The fundamental focus point of this course is to explain you, what the feature is, using a simple and easy to understand example and also help you understand how you can apply it in real world software development.
It is imperative that if you are looking to be a Java professional, you must possess good clarity in programming fundamentals, and applying the object oriented programming (OOP) features in your code. This can be achieved provided that you know answers to few questions such as what the feature is all about? when to apply? how to apply? as understanding these features are very critical for software development.
Learn Object Oriented Programming features through Java Programming Language.
Gain the insights about how you can apply them in the real time in software development.