
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