[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