[Haskell-beginners] containers and extensibility, typeclasses vs. multiple value constructors

Daniel Fischer daniel.is.fischer at web.de
Mon Sep 6 09:14:04 EDT 2010


On Monday 06 September 2010 06:47:16, Greg wrote:
> I think I'm starting to get a sense for this, but want to check my
> understanding...
>
> I'm writing a program that plots data.  I want to be able to have
> multiple plots simultaneously-- some are scatter plots, some are lines,
> some are functions, etc.  I think there are two choices in how to define
> these different plot styles: I can have one type with constructors for
> scatter, line, function, etc; or I can have independent types for each
> plot style and a typeclass to define the shared functionality.
>
> I want to be able to treat these plots abstractly within the program: I
> don't care what style of plot it is at certain levels of processing, I
> just know I want to render it.  This suggests a typeclass handling,
> where the typeclass has a render method.
>
> However, I also want to maintain a list of these plots so I can 'mapM_
> render plotlist'.  I believe I can only create a list of plots if
> they're all the same type,

Right.

> therefore they must be multiple constructors
> for the same type.  'render' then will need to be handled by pattern
> matching.

Weeeelll,

>
> The last piece of this, is that it would be nice to be able to add new
> plot styles later.  Ideally this will all become a library for me, and
> I'd like to be able to add a new plot style without having to modify the
> existing code.  I think the only way to do this is through the typeclass
> mechanism, where I can create the new type and create a class instance
> in my local code.
>
> So, am I stuck with this tradeoff?  I can either put my plots in a
> container using one type and multiple constructors, or I can make the
> system extensible using typeclasses?

you can combine the approaches. As long as all you want to do with your 
container is rendering the contents, 

{-# LANGUAGE ExistentialQuantification #-}

class Plot a where
    render :: a -> IO ()
    describe :: a -> String

data SomePlot = forall p. Plot p => SomePlot p

instance Plot SomePlot where
    render (SomePlot p) = render p
    describe (SomePlot p) = describe p

gives you a class, so you can define new plot types without modifying the 
library, and a wrapper type, so you can stick plots of different types in 
the same container after wrapping them.
Once they're wrapped, you can't use anything but the methods of the Plot 
class on them, though, so if you want to do anything else with the 
container's contents, that won't work (you can do something with an 
additional Typeable constraint).

http://www.haskell.org/haskellwiki/Existential_type for more.

>
> Thanks--
>  Greg
>

HTH,
Daniel



More information about the Beginners mailing list