[Haskell-cafe] Client-extensible heterogeneous types

Alexander Solla ajs at 2piix.com
Tue Oct 12 18:28:32 EDT 2010

On Oct 12, 2010, at 4:24 AM, Jacek Generowicz wrote:

> 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.)

Is there any particular reason why you want to actually to mirror  
Python code?  I think that letting the programmer design domain  
specific control structures is rather the point of Haskell.  Instead  
of relying on a one-sized fits all solution (which only really fits  
one kind of problem), you write your own.  And it is typically easier  
to write the control structure than it is to implement it using the OO  
patterns, because of the notion of irreducible complexity.  For  
example, the Factory pattern constructs a functor.  You can write the  
essential semantics of doing this with a single Functor instance,  
instead of writing multiple classes which implement the semantics,  
while relying on implicit, and possibly ill-fitting semantics of  
method dispatch.  The other OO patterns make this objection stronger.   
If you can write a UML diagram, you can turn it into a commutative  
diagram, and write less code by implementing its arrows.

An OO class hierarchy is a very specific functor over objects (which  
attaches methods to objects).  Haskell provides the Functor type  
class.  Write your generic functions for specific functors:

-- The varying "input" types.  Will be attached to arbitrary values by  
the Functor instance.

data A = A	-- Variant 1
data B = B	-- Variant 2

-- Some normalized Output type.
data Output = Output

-- The new control structure.  
data Attaches a = AttachesA A a
                 | AttachesB B a

-- Stick your conditional (varying) semantics in here.  Corresponds to  
-- The output presumably depends on whether A or B is attached, so  
this function is not equivalent 
-- to something of the form fmap (f :: a -> Output) (attaches ::  
Attaches a) 

runAttaches :: Attaches a -> Attaches Output
runAttaches = undefined

-- This corresponds roughly to  
processedOutputs :: [Attaches a] -> [(Attaches Output)]
processedOutputs as = fmap runAttaches as

-- Functor instance.  Now you have a way to treat an (Attaches a)  
value just like you would an a. (modulo calling fmap)
instance Functor Attaches where
          fmap f (AttachesA A a) = (AttachesA A (f a))
          fmap f (AttachesB B a) = (AttachesB B (f a))

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20101012/87be238b/attachment.html

More information about the Haskell-Cafe mailing list