[Haskell-cafe] Thoughts on Haskell and OOP

Kevin Van Horn kevin at ksvanhorn.com
Thu Jan 1 19:28:21 EST 2009

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
to do the kinds of things you would use classes and inheritance for in  
OO languages.

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.

Object-oriented programming is then object-based programming plus  
class hierarchies and inheritance.  Why are these useful?

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?

Yes, we can.  Let's consider the Haskell analog of an immutable C++  
base class:

   struct Base {
     virtual ~Base();
     virtual int foo() const;
     virtual int bar(int n) const;

   class derived :: public Base {
     ... data members ...
     derived(T_1 arg1, ..., T_k argk);
     ... implementations of the virtual functions ...

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:

   data Base = Base { foo :: Int, bar :: Int -> Int }

   derived :: T_1 -> ... -> T_k -> Base
   derived a_1 ... a_k = Base { foo = ...; bar = bar } where bar n = ...

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:

   virtual int bar(int n);

The Haskell analog then changes to

   data Base = Base { foo :: Int, bar :: Int -> (Int, Base) }

   derived :: T_1 -> ... -> T_k -> Base
   derived a_1 ... a_k = Base { foo = ...; bar = bar } where
     bar n = (..., (derived a_1' ... a_k'))

(Here a_1', ..., a_k' are k expressions involving n and a_1, ..., a_k.)

What do the rest of you think?  Is my analysis correct?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20090101/59a3825b/attachment-0001.htm

More information about the Haskell-Cafe mailing list