<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. &nbsp;I've been thinking about why this is so. &nbsp;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&nbsp;</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. &nbsp;At the most basic level we have what some call object-based programming. &nbsp;This amounts to support for data hiding and abstract data types. &nbsp;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. &nbsp;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. &nbsp;(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.) &nbsp;(For those more familiar with Python, "duck typing" is the analog of interface inheritance for a dynamically-typed language.) &nbsp;Interface inheritance&nbsp;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. &nbsp;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. &nbsp;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;">&nbsp;&nbsp;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;">&nbsp;&nbsp; &nbsp;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;">&nbsp;&nbsp; &nbsp;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;">&nbsp;&nbsp; &nbsp;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;">&nbsp;&nbsp;};</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;">&nbsp;&nbsp;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;">&nbsp;&nbsp; &nbsp;... 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;">&nbsp;&nbsp;public:</span></font></div><div><font class="Apple-style-span" face="'Courier New'" size="4"><span class="Apple-style-span" style="font-size: 14px;">&nbsp;&nbsp; &nbsp;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;">&nbsp;&nbsp; &nbsp;... 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;">&nbsp;&nbsp;};</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;">&nbsp;&nbsp;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;">&nbsp;&nbsp;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;">&nbsp;&nbsp;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;">&nbsp;</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. &nbsp;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;">&nbsp;&nbsp;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; ">&nbsp;&nbsp;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; ">&nbsp;&nbsp;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; ">&nbsp;&nbsp;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; ">&nbsp;&nbsp; &nbsp;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? &nbsp;Is my analysis correct?</span></font></div><div><br></div></span></span></font></div></div></body></html>