
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.