Haskell's overlooked object system

A "major new release" from Oleg Kiselyov and Ralf Lämmel:

In a first phase, we demonstrate how far we can get with object-oriented functional programming, if we restrict ourselves to plain Haskell~98. In the second and major phase, we systematically substantiate that Haskell~98, with some common extensions, supports all the conventional OO features plus more advanced ones, including first-class lexically scoped classes, implicitly polymorphic classes, flexible multiple inheritance, safe downcasts and safe co-variant arguments. Haskell indeed can support width and depth, structural and nominal subtyping. We address the particular challenge to preserve Haskell's type inference even for objects and object-operating functions. Advanced type inference is a strength of Haskell that is worth preserving. Many of the features we get "for free": the type system of Haskell turns out to be a great help and a guide rather than a hindrance.

You can download the paper and OOHaskell from here.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

seems cool

I gave the paper a loose read last night, and, overall, I'm impressed. But, having objects locked up in the IO monad wouldn't be my personal cup of tea.

does Haskell98 needs extensions to support OO?

Haskell98 can easily support the major concepts of OO, inheritance, encapsulation and message passing. Lambda functions can be used as interfaces. For example:

module Test where
    foo1 :: Integer -> Integer -> Integer
    foo1 p = \x -> x * p
    
    foo2 :: Integer -> Integer -> Integer
    foo2 p = \x -> x + p
    
    foo1_msg = foo1 100
    foo2_msg = foo2 200
    
    foo_list = [foo1_msg , foo2_msg]

In the above example, we can see two 'constructor' functions 'foo1' and 'foo2' that create two interfaces of the same type but with different implementation: 'foo1' does a multiplication, while 'foo2' does an addition. An object can easily be represented as a collection of functions.

How well Haskell98 can encode objects

axilmar wrote:

An object can easily be represented as a collection of
functions.

Yes, of course. One should point out that these functions (methods)
generally have different interfaces, so that collection must be a
record rather than a list. But records in Haskell98 are not overtly
extensible, and exhibit no record polymorphism. Implementing
inheritance then becomes a challenge -- how can you take a record Foo,
derive an extended record Bar, and still be able to pass Bar (which is
of a different type!) to a function that takes Foo. Open recursion
(calls to `self' that derived objects can interpose upon) is another
challenge. That challenges are surmountable. Section 3 of our paper
lists all, to the best of our knowledge, approaches to
encoding of objects in Haskell98, along with their strong and weak
points.