[Haskell-cafe] Client-extensible heterogeneous types

Jacek Generowicz jacek.generowicz at cern.ch
Tue Oct 12 07:24:54 EDT 2010


Greetings,

I'm looking for dynamic dispatch on extensible sets of types.

Here is a more detailed explanation of what I mean:

########################################################################

# Consider the following Python code as representative of something
# you might see in Object-Orineted programs in all sorts of languages.

# Create an abstract type

from abc import ABCMeta, abstractmethod

class Abstract:

     __metaclass__ = ABCMeta

     @abstractmethod
     def method(self):
         pass

# Provide some reifications of the abstract type

class Variant1(Abstract):
     def method(self):
         return "Variant 1 stuff"

class Variant2(Abstract):
     def method(self):
         return "Variant 2 stuff"

# Provide some utilities to process these data

def heterogeneousProcessor(data):
     return [datum.method() for datum in data]

# If you wrap all the above up in a library, clients can easily extend
# it with their own new types which will still work within the
# framework

class ClientDefined(Abstract):
     def method(self):
         return "Client-defined stuff"


heterogeneousContainer = [Variant1(), Variant2(), ClientDefined()]

result = heterogeneousProcessor(heterogeneousContainer)

########################################################################

------------------------------------------------------------------------

-- In Haskell, on the one hand, the heterogeneity is easily provided
-- by algebraic data types

data AbstractHeterogeneous = VariantHeterogeneous1 |  
VariantHeterogeneous2

methodHeterogeneous VariantHeterogeneous1 = "Variant 1 stuff"
methodHeterogeneous VariantHeterogeneous2 = "Variant 2 stuff"

heterogeneousProcessor dataa = [methodHeterogeneous datum | datum <-  
dataa]

heterogeneousContainer = [VariantHeterogeneous1, VariantHeterogeneous2]

resultHeterogeneous = heterogeneousProcessor heterogeneousContainer

-- But in order to extend the set of variants, the client would have
-- to modify the source code, changing the definiton of
-- AbstractHeterogeneous and methodHeterogeneous, both of which belong
-- to the library.

------------------------------------------------------------------------
-- On the other hand, the extensibility is easily provided by type
-- classes

-- Library code:

class AbstractExtensible a where
     methodExtensible :: a -> String

instance AbstractExtensible () where
     methodExtensible _ = "Variant 1 stuff"

instance AbstractExtensible Char where
     methodExtensible _ = "Variant 2 stuff"

-- Client extension:

instance AbstractExtensible Int where
     methodExtensible _ = "Client-defined stuff"

-- but in this case, there is no heterogeneity: you cannot create the
-- equivalent of heterogeneousContainer above

-- heterogeneousExtensibleContainer = ????

resultExtensible :: [String]
resultExtensible = [methodExtensible (), methodExtensible 'a',  
methodExtensible (1::Int)]
------------------------------------------------------------------------

I can't see a Haskell solution which combines both of these orthogonal
features without losing the benefits of the type system. (For example,
I could create my own, weak, type system with tags to identify the
type and maps to do the dispatch.)

So my question is, what would be the Haskell approach to combining
heterogeneity (as provided by variant (algebraic) types) with
type-extensibility (as provided by type classes), without losing the
benefits of Haskell's type system?

I haven't looked into Template Haskell, but i guess that it is likely  
to provide a solution.
But is there a solution in plain Haskell?

Thanks.



More information about the Haskell-Cafe mailing list