[Haskell-cafe] Execution Contexts

Keean Schupke k.schupke at imperial.ac.uk
Sun Nov 28 07:53:18 EST 2004


Benjamin Franksen wrote:

>Timber (formerly O'Haskell) has gone this way. Its object model is defined 
>(and in fact was implemented) by a straight-forward translation into a 
>(state) reader monad transformer over the IO monad. It is noteworthy that in 
>this translation the (local) state of a Timber object is not a record but 
>just an (IORef to an) anonymous tuple. [It is true that they added 'real' 
>records and subtyping to the language but these additions are completely 
>orthogonal to the object model. Records are merely used to group the monadic 
>actions that define the interface of an object into a suitable type hierarchy 
>(in order to model a weak form of interface inheritance).]
>  
>
Well without propper records you cannot do inheritance and other
things relavent to the object model - so it is not orthogonal - but it
is certainly true that you can define the state of an object using an
IORef, and local scoping can provide the data-hiding necessary.

We are using HLists to provide records and sub-typing, which are
implemented using ghc's existing extensions to the class system
(multi-parameter type and fundeps) - so no language extensions are
necessary for these features - Haskell already has them, and they
can be used quite reasonably from a library without syntax extensions.

>So, one of the things I learned when studying Timber's object model is that 
>records (or modules) with mutable fields (and inheritance and so on) are 
>*not* the whole story. The most interesting aspect is how objects react to 
>external stimulus, i.e. their representation as monadic effects.
>  
>
Well the records implement method dictionaries, so they determine
which inheritance and interface methods are possible.

>One *can* program in such a way in Haskell. What's missing is not so much 
>records or first class modules, nor top-level IO actions (safe or not), but 
>suitable syntactic sugar to alleviate the burden of having to lift (sic!) all 
>IO actions to a suitable object/context monad.
>  
>
Erm no, all the objects can be implemented directly in the IO monad
if you so wish, so no lifting is necessary... here is an example object
in actuall Haskell code using the HList library...

 >point = do
 >      x <- newIORef 0
 >      returnIO $ mutableX .=. x
 >       .*. getX .=. readIORef x
 >       .*. moveD .=. (\d -> modifyIORef x ((+) d))
 >       .*. emptyRecord

And here's the object in use:

 >myFirstOOP = do
 >     p <- point
 >     p # getX >>= print
 >     p # moveD $ 3
 >     p # getX >>= print

As you can see no lifting or awkwardness involved... the syntax looks
very much like the OCaml example it was ported from. Admittedly a little
syntactic sugar may make it more palatable to OO programers. (But
notice how all the types for the objects methods are inferred by the
compiler...)

    Keean.



More information about the Haskell-Cafe mailing list