1 Introduction
One of the main advantages of functional programming (FP) languages is that proving properties of most functional programs—programs written using functional programming languages such as ML—is often straightforward. It is wellknown that traditional (automatic) theorem proving (which we abbreviate TTP) and functional programming go hand in hand [8]. In fact the development of FP shows that TTP was the original raison d’être for FP.
To see how and why that is the case, it should be noted that TTP is typically based on tactics and tacticals. Tactics and tacticals are higherorder functions. Tacticals are even higherorder than tactics, since tacticals take other tactics—higherorder functions—as their input and produce them as results.
Further, the formal verification of the correctness of functional software is usually done using functional software tools, so as to have a degree of mathematical confidence in the capabilities of these proving tools (also called proof assistants). That is, not only is the proof of the correctness of a function in a functional program itself a function, but most of the professional software tools used in TTP (e.g., Coq and Isabelle) are themselves—or at least their most important core (i.e., their “proving engine”, based on tactics and tacticals)—written mostly in functional languages.^{1}^{1}1That is, a functional program is used to reason about another functional program to produce a functional program—a proof of the correctness of the input program—as its result: we have functional processing of functional input to produce functional output. Hence, the very strong connection between TTP and FP.
In this work we suggest a new style of theorem proving, objectoriented theorem proving (OOTP), that goes hand in hand with objectoriented programming (OOP) in the same way as TTP goes with FP. A main aim of OOTP is to make proving properties of a large subset of objectoriented programs as equally straightforward as TTP makes it for a large subset of functional software.^{2}^{2}2This subset includes referentiallytransparent, provablyterminating OO programs. As such, our work justifies OO developers adopting the socalled “almostfunctional” style of OO programming, where developers largely avoid imperative (i.e., nonreferentiallytransparent) features of OO languages (such as mutable fields and variables). It should be noted though that in fact this “almostfunctional” style of OOP seems to be not necessary! As Paulson notes in [8, p.58], any procedural code (including one containing goto statements and assignment statements, the least opaque code) can be translated into a set of mutually recursive functions of a functional program. In other words, as we explain in this work, the opaque code can be translated into an object. (See Appendix A for the translation of the code in [8, p.58] to OO code.) Employing OOTP, objects seemingly can be used to reason even about the most opaque code.
2 ObjectOriented Theorem Proving
To introduce OOTP, it should be first and foremost noted that OOTP generalizes and subsumes TTP. In particular, OOTP generalizes the notions of axioms, theorems and inference rules of TTP to simultaneous axioms, simultaneous theorems and simultaneous inference rules, where simultaneity of a defined set of axioms, theorems or inference rules allows interdependence between the simultaneouslydefined axioms, theorems or inference rules (i.e., they can be defined mutuallyrecursively). In the sequel we explain in more detail how OOTP is defined as a generalization of TTP.
In TTP, each axiom is a primitive theorem, while each inference rule is a function from theorems to theorems [8]. In OOTP, we have each set of simultaneous axioms as a set of simultaneous primitive theorems, while each set of simultaneous inference rules is an object that maps—i.e., whose methods map—simultaneous theorems to simultaneous theorems.
Further, in TTP (as first suggested by Milner, for LCF [9, 6]) regular FP type checking ensures that theorems could be made only by axioms and inference rules. Applying inference rules to already known theorems constructs proofs, rule by rule, in the forward direction [8]. In OOTP, on the other hand, regular OO type checking will ensure that simultaneous theorems could be made only by simultaneous axioms and simultaneous inference rules. Applying simultaneous inference rules to already known simultaneous theorems constructs simultaneous proofs (as one unit, called an OO proof, or an object), rule by rule, in the forward direction.
Moreover, tactics in TTP permit a more natural style, backward proofs. A tactic in TTP is a function from goals to subgoals, justified by the existence of an inference rule going the other way. The tactic actually returns this inference rule (as a function) in its result: tactics are higherorder functions [8]. Similarly, in OOTP we have OO tactics, which permit a more natural style, backward OO proof. An OO tactic is an object that maps—i.e., whose simultaneouslydefined methods map—(simultaneous) goals to (simultaneous) subgoals, justified by the existence of a set of simultaneous inference rules going the other way (i.e., from subgoals to goals). The OO tactic actually returns this set of simultaneous inference rules (as an object) in its result: OO tactics are higherorder objects.
Finally, tacticals in TTP provide control structures for combining simple tactics into complex ones. The resulting tactics could be combined to form still more complex tactics, which in a single step could perform hundreds of primitive inferences. Tacticals are even more higherorder than tactics [8]. Similarly, OO tacticals in OOTP provide control structures for combining simple OO tactics into complex ones. The resulting OO tactics could be combined to form still more complex OO tactics, which in a single step could perform hundreds of primitive OO inferences. OO tacticals are even more higherorder than OO tactics.
Table 1 summarizes the similarities and differences between OOTP and TTP.
TTP  OOTP 

Axiom  Simultaneous Axioms 
(OO Axiom)  
Theorem  Simultaneous Theorems 
(OO Theorem)  
Inference Rule  Simultaneous Inference Rules 
(OO Inference Rule)  
Proof (Function)  Simultaneous Proofs 
(OO Proof; Object)  
Tactic  OO Tactic 
(Higherorder function)  (Higherorder object) 
Tactical  OO Tactical 
(Higherorder function)  (Higherorder object) 
3 Remaining Work
After overcoming some initial unfamiliarity it is easy to recognize that, when formalized, OOTP, as presented so far, seems to be a straightforward, relativelymild generalization of TTP. It should be noted, however, that objectoriented programming (from which OOTP gets inspiration) is characterized by two features that make it distinct and intricate, and thus—we believe—more practically useful than functional programming (from which TTP gets inspiration). These two features are (1) encapsulation and (2) (type) inheritance and subtyping.
3.1 Selfawareness and Inheritance
Encapsulation, in OOP, first and foremost means the binding together of a collection of related methods and fields in one unit (a capsule/an object). In addition, encapsulation in OOP refers to the autognosticism property of objects (i.e., their selfawareness, via the parameter this, or self, that is passed implicitly to all methods of an object). Encapsulation in OOP also frequently refers to the ability to hide some implementation details. (The information hiding sense of encapsulation is not characteristic to OOP, however, since it is supported in FP, for example, via abstract data types.)
Type inheritance, and subtyping, in OOP refer to the inheritance and reuse of object types and of behavioral contracts by subclasses (and their corresponding subtypes) from superclasses (and their corresponding supertypes), and to the preservation and refinement of types and contracts in the subclasses/subtypes.
Providing a mathematical and practicallyuseful meaning of encapsulation in OOTP (which we partially did above) and of inheritance and subtyping in OOTP (which yet remains to be done, but which we expect to involve some notion of specification inheritance and/or theorem refinement) should make OOTP a more intricate and more powerful generalization of TTP.
3.2 ObjectOriented Software Verification (OOSV)
We predict that a precise and full definition of encapsulation and inheritance in OOTP will immediately enable establishing an obvious and direct method for reasoning about objectoriented software and verifying its properties. Specifying the details of this method is work that remains to be done.
4 Comparisons and Some Philosophy
4.1 OOTP versus TTP … and OOSV
Just as OOP is more practically useful than FP (as demonstrated by the practical popularity of OO programming languages as compared to that of functional programming languages^{3}^{3}3The skeptic reader should check by themselves the TIOBE index and langpop.com, or do an online survey to compare the popularity of OOP with that of FP. We also invite the reader to check our related work ‘From FP to OOP (or, Java for the Working ML Programmer)’ [4].), we believe OOTP might also prove to be more practically useful in proving theorems about the realworld—intrinsically complex, interconnected and interdependent?—than TTP is. In particular, as hinted to above we believe OOTP, given its inherent objectorientation, can be used to reason about and verify OO software (OOSV) in a more natural manner.
4.2 OOP versus FP
In this section we briefly discuss the relation between OOP, as a computer programming paradigm centered around objects, and FP, as a paradigm centered around functions, by presenting an analogy and some philosophy. We offer what we believe is a novel prespective but we do not go into plenty of details given that the topic has been discussed, extensively but inconclusively, in the research literature (e.g., as revealed by [7] and related work, or by an online search for ‘the expression problem’).
An Analogy.
Based on our modeling of nominal OOP and structural OOP [1], in our opinion the main and most fundamental difference between OOP and FP is that OOP embraces mutual recursion wholeheartedly (mutually recursive methods come essentially for free in OOP) while FP embraces mutual recursion reluctantly (mutually recursive functions require special constructs in FP, and even then their use is discouraged^{4}^{4}4See the code example in Appendix A for an FP warning against some definitions of mutuallyrecursive nonimperative functions.).
To an extent this difference is analogous to the difference between natural languages that consider words as the main units of the language^{5}^{5}5Wordbased languages; most natural languages fall in this category since a word—a finite sequence of letters—is the smallest unit that has meaning in such languages. and natural languages that consider characters (or letters) as the main fundamental units of speech and language^{6}^{6}6Characterbased languages; very few natural languages fall in this category in which most if not all single characters, or “letters,” have meanings..
We find this analogy appropriate because in OOP an object, at its very core, is a set of functions (the methods of the object, possibly mutually recursively defined). That is, in OOP an object is a finite set of tightly related functions but each method in an object, on its own, is not considered as a fundamental independent unit (i.e., in OOP rarely, or at least lessfrequently, does a single method have an independent meaning, outside the context of an object) but rather the grouping and binding of the set of functions (as methods) in one unit (as an object, via the notion of this/self) is the fundamental, smallestmeaningful unit in OOP. Functional languages, on the other hand, consider it to be the norm that each function has an independent meaning, and they allow mutuallyrecursive functions usually only as a rare (and “complex”) exception.
As such, akin to the view of words and letters in most natural languages, OOP considers mutuallydependent functions as the norm (and thus embraces their grouping as a fundamental unit: an objects) while considering single functions having independent meanings as being an exception (i.e., only very few objects have single meaningful methods in an OOP program, e.g., the equals() method of class Object^{7}^{7}7Even equals() is not quite independent. Its definition usually requires to be “in sync” with the definition of hashCode() [5].). Functional programming, on the other hand, similar only to very few natural languages, considers functions having independent meanings as the norm (as we explained above).
A Philosophical Note.
Consider the following three questions:

Is FP superior to OOP (as some PL researchers and theoreticians may claim) or vice versa (as some industrial software developers may claim)?

To which of the two programming paradigms belongs the future of computer programming?

Is our world fundamentally composed of interdependent and complex entities (OOP) or is it fundamentally composed of independent and simple entities (FP)?
We believe these three questions to be somewhat philosophical questions, whose answers will always remain controversial, rather than being technical questions whose answers can be resolved scientifically. While having our own personal answers to these questions (squarely in favor of OOP), we hope the brief discussion above—including the illustrating analogy with natural languages—sheds some light on why we believe these questions are lesser technical and scientific ones and more controversial and philosophical ones.^{8}^{8}8We believe research on FP should aim to suggest how OOP can be improved—e.g., as was done in Java 8.0—but should not aim for FP replacing OOP.^{9}^{9}9Our opinion is formed based on nothing related to any software efficiency arguments, in spite of their importance. We believe efficiency arguments are fundamentally ambivalent, agnostic or neutral towards the ‘OOP versus FP’ question. Efficiency of computer software, particularly time and space efficiency, is almost always due to the existence of imperative programming features in a programming language. Imperative programming features, which are usually found in OOP but not FP languages, are not inherent or characteristic of OOP, and can be added to a FP language with little additional complexity to the language (as ML—a popular functional language—demonstrates).
5 Ideas to Incorporate Later
6 Implementation/Proof of Concept
We are currently working on further exploration and refinement of our ideas on OOTP by implementing a basic OO theorem prover in three programming languages: ML (FP), Java (OOP) and Scala (OOP/FP), using theorem prover ideas from our implementation of Paulson’s Hal [8] and our update [2] to Velleman’s Proof Designer [10, 11]. Early versions of our code should be available on sourceforge and github in the near future. Stay tuned.
References
 [1] Moez A. AbdelGawad. A domaintheoretic model of nominallytyped objectoriented programming. Electronic Notes in Theoretical Computer Science (ENTCS), 301:3–19, 2014.
 [2] Moez A. AbdelGawad. Proof Designer 2.0. http://sf.net/proofdesigner2, 2016.
 [3] Moez A. AbdelGawad. Category theory for modeling OOP (extended abstract). Accepted at The Nordic Workshop on Programming Theory (NWPT’17), Turku, Finland, November 13, 2017. (Full version available at arXiv.org: 1709.08056 [cs.PL]).
 [4] Moez A. AbdelGawad. From FP to OOP (or, Java for the working ML programmer). To appear, 2018.
 [5] Joshua Bloch. Effective Java. Prentice Hall PTR, 2008.
 [6] Michael J. Gordon, Arthur J. Milner, and Christopher P. Wadsworth. Edinburgh LCF: A Mechanized Logic of Computation. SpringerVerlag, 1978.
 [7] David B. MacQueen. Should ML be objectoriented? Formal Aspects of Computing, 13:214–232, 2002.
 [8] Lawrence C. Paulson. ML for the Working Programmer. Cambridge University Press, 1996.
 [9] Gordon D. Plotkin. LCF considered as a programming language. Theoretical Computer Science, 5:223–255, 1977.
 [10] Daniel J. Velleman. How To Prove It: A Structured Approach. Cambridge University Press, second edition, 2006.
 [11] Daniel J. Velleman. Proof Designer. http://www.cs.amherst.com/~djv/pd/, 2006.
Appendix A Opaque Code Translated to OOP and FP Code
a.1 Imperative to OOP
The imperative code

var x := 0; y := 0; z := 0;F: x := x+1; goto GG: if y<z then goto F else (y := x+y; goto H)H: if z>0 then (z := zx; goto F) else stop
can be translated to the following nonimperative OO code

class C {final x, y, z: int// constructorC(xx,yy,zz: int) { x = xx; y = yy; z = zz }C F() { new C(x+1,y,z).G() }C G() {if y < z then this.F()else new C(x,x+y,z).H() }C H() {if z > 0 then new C(x, y, zx).F()else this }}
Calling new C(0,0,0).F() returns an object equivalent to new C(1,1,0), as expected.
The code can be also translated to the following (more succinct, but harder to reason about) imperative OO code

class IC {x, y, z: intIC(xx,yy,zz: int) { x := xx; y := yy; z := zz }void F() { x := x+1; G() }void G() {if y < z then F()else { y := x+y; H() }}void H() { if z > 0 then { z := zx; F() }}}
On an object ic = new IC(0,0,0) calling ic.F() terminates with ic equivalent to new IC(1,1,0), as expected.
It should be noted that in the OO code above all unqualified field references and methods calls are implicitly done via this.
a.2 Imperative to FP
For comparison purposes, the corresponding mutuallyrecursive functional translation (adapted from the code in [8, p.58]) of the opaque imperative code above looks like

type int_triple = int * int * intfun F(x,y,z: int): int_triple =G(x+1,y,z)andG(x,y,z: int): int_triple =if y<z then F(x,y,z)else H(x,x+y,z)andH(x,y,z: int): int_triple =if z>0 then F(x,y,zx)else (x,y,z);
Calling F(0,0,0) returns (1,1,0).
The functional code makes us note that

All variables are passed explicitly as parameters in the code. With many variables, the code may not scale well.

The code, and functional programming more generally, do not support open recursion. Method calls in OOP are virtual (i.e., are made via this at runtime, which is sometimes called dynamic/latebinding) by default in most OO languages. Function calls in FP, however, are always nonvirtual (i.e., are always staticallybound). Unlike in OOP, FP lacks a notion of inheritance/subclassing that allows for late/dynamicrebinding. An alternative to open recursion in FP is to make use of higherorder functions—i.e., functionals—that take other functions, dynamically, as parameters).

Finally, and most importantly, because referential transparency is frequently stated as a main advantage of functional programming, Paulson [8, p.58], in an implicit warning against mutuallyrecursive functional programming (after presenting code similar to the functional code above, notably nonimperative), remarks that
Functional programs are referentially transparent, yet can be totally opaque. If your code starts to look like this, beware!
It should be noted that mutual recursion, and even open mutual recursion, is embraced wholeheartedly in OOP, due to the seemingly natural and intuitive realworld modeling capabilities of mutual recursion. It is a main goal of OOTP to make reasoning about such code (i.e., nonimperative but mutuallyrecursive code, expressed as OO code) as natural and straightforward (“transparent”) as TTP makes it for (nonimperative and nonmutuallyrecursive) functional code.