<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;">Haskell has been around in one form or another for nearly two decades now, yet has never been extended with explicit support for object-oriented programming. I've been thinking about why this is so. I've come to the conclusion that Haskell simply doesn't need any explicit OOP support -- algebraic datatypes, modules, lazy evaluation, and first-class functions give you everything you need </span></font><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;">to do the kinds of things you would use classes and inheritance for in OO languages.</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;">To see why this is so, let's think about what OOP is. At the most basic level we have what some call object-based programming. This amounts to support for data hiding and abstract data types. Haskell's module system handles this function quite well, without any need to introduce a special concept of "class" (in the OO sense) nor private vs. public class members.</span></font><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;">Object-oriented programming is then object-based programming plus class hierarchies and inheritance. Why are these useful?</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><span class="Apple-style-span" style="font-family: 'Courier New'; font-size: 14px; ">Properly used, OOP is all about interface inheritance, not implementation inheritance. (At least in C++, implementation inheritance -- inheriting the data members and method implementations of a base class -- usually leads to bad design, and is discouraged by the experts.) (For those more familiar with Python, "duck typing" is the analog of interface inheritance for a dynamically-typed language.) Interface inheritance allows you to write procedures that operate on the base-class interface, but can be applied to objects of any type derived from the base class. Can we do this in Haskell?</span></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;">Yes, we can. Let's consider the Haskell analog of an immutable C++ base class:</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> struct Base {</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> virtual ~Base();</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> virtual int foo() const;</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> virtual int bar(int n) const;</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> };</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> class derived :: public Base {</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> ... data members ...</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> public:</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> derived(T_1 arg1, ..., T_k argk);</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> ... implementations of the virtual functions ...</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> };</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;">Haskell has no direct analog of object classes and virtual methods, but you can use lazy evaluation and first-class functions to achieve the same result:</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> data Base = Base { foo :: Int, bar :: Int -> Int }</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> derived :: T_1 -> ... -> T_k -> Base</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> derived a_1 ... a_k = Base { foo = ...; bar = bar } where bar n = ...</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> </span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;">The analog of a mutable C++ base class is a little bit more involved, but not much. Suppose that we change bar(int) to be a mutating method in the C++ Base class:</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"> virtual int bar(int n);</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;">The Haskell analog then changes to</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><span class="Apple-style-span" style="font-family: Helvetica; font-size: 18px; "><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px; "> data Base = Base { foo :: Int, bar :: Int -> (Int, Base) }</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px; "><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px; "> derived :: T_1 -> ... -> T_k -> Base</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px; "> derived a_1 ... a_k = Base { foo = ...; bar = bar } where</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px; "> bar n = (..., (derived a_1' ... a_k'))</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;">(Here a_1', ..., a_k' are k expressions involving n and a_1, ..., a_k.)</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;"><br></span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;">What do the rest of you think? Is my analysis correct?</span></font></div><div><br></div></span></span></font></div></div></body></html>