Extensible Algebraic Data Types

Ashley Yakeley ashley@semantic.org
Fri, 2 Mar 2001 17:36:15 -0800

I think it would be useful to extend Haskell so that one could create 
algebraic data types in one module that could be union-extended in 
another. Something like this:

data Thing = CharThing Char | IntThing Int | _


data Thing |= StringThing String

This would be useful for two reasons:

1. You could do something akin to dynamic typing without unreasonably 
stressing the ideas behind the Haskell type system:

data BaseExtension = _
data Base = MkBase (Char,Int,BaseExtension)


data Derived = MkDerived (Char,Int,Int,Int)
data BaseExtension |= MkDerivedExtension (Int,Int)

upcast :: Derived -> Base
upcast (MkDerived (a,b,c,d)) = MkBase (a,b,MkDerivedExtension(c,d))

downcast :: Base -> Maybe Derived
downcast MkBase (a,b,MkDerivedExtension(c,d)) = Just (MkDerived (a,b,c,d))
downcast MkBase (a,b,_) = Nothing

2. You'd have a way of autogenerating values similar to LISP's gensym:

data Token = _ deriving Eq


data Token |= ThisToken
data Token |= ThatToken
data Token |= BunchOfTokens Int

Of course this extension to Haskell begs another, virtual or generic 
functions. I'm not sure how to do this properly while maintaining the 
principle that an expression has the same value regardless of other 
modules loaded.

data Thing = CharThing Char | IntThing Int | _

f1 :: Thing -> Int
f1 (CharThing c) = ord c
f1 (IntThing i) = i
-- somehow allow cases to be inserted later here
f1 _ = 0

-- multiple dispatch
f2 :: Thing -> Thing -> Int
f2 (IntThing i) (IntThing j) = i + j
-- might want cases inserted here,
-- provided they don't cause trouble
f2 (IntThing i) _ = i
-- or here
f2 _ (IntThing i) = i + 1
-- or here
f2 _ _ = 0

Are these ideas something worth thinking about? Or would such extensions 
compromise important principles behind Haskell?

Ashley Yakeley, Seattle WA