[Haskell-cafe] Refactoring type-class madness

Andrew Webb andrew.webb at gmail.com
Thu Jul 15 23:22:53 EDT 2010

Hi there haskellers,

I have thoroughly confused myself with type-classes in a haskell
system I am writing, and I was wondering if anyone had some useful
suggestions to get me out of my mess. I apologise if this is all long
and rambling, but that maybe why I can't solve it...

The system itself performs analyses on data from human eye-tracking
experiments, where the tracking data is simplified from raw positional
data into "events" which are either fixations or saccades. This is
easy to do:

data Event = Fixation {...} | Saccade {...}

Because, at the basic level all of the experiments share this type of
data, it seems that I should be able to write analysis functions that
work for any experiment. However, the experiments differ in the
stimuli used, and associated with each stimulus set is a set of
"milestones" that give times at which important things happen in the
stimuli, and "regions of interest" that give areas of the visual scene
that are considered important. For a single experiment I would have:

data Experiment = Exp [Trial]
data Trial = Trial [Event] (Map MileStone Time)
data MileStone = M1 | M2 | ...

and the analysis functions can take an experiment, use the events and
the milestones, and return whatever.

The problem arises when I want to represent a second experiment. I
assumed the way to solve this was with a type class:

class ExperimentClass a

data ExperimentOne = Exp [Trial]

instance ExperimentClass ExperimentOne

and have the analysis functions take (ExperimentClass a) => a -> ...
This, however, necessitates a change to Trial as well, because the
MileStones for each experiment are different:

class MileStoneClass a
data (MileStoneClass a) => Trial a = Trial [Event] (Map a Time)

which means that:

data (MileStoneClass a) => ExperimentOne a = Exp [Trial a]

and maybe even:

class (MileStoneClass b) => ExperimentClass a b
instance ExperimentClass ExperimentOne ExOneMileStones

which all seems fine. But then I need to add regions of interest, and
a corresponding type parameter, and a couple of more things with type
parameters, and I get something like:

class (MileStoneClass b, RegionClass c, ... d, ... e) =>
ExperimentClass a b c d e

which is a lot of type parameters that are all dependent on a, since
the experiment defines the milestones etc. I can use fundeps to
enforce that in the type system, but it is still quite messy.

So, I was wondering whether there was something wrong with my basic
model which leads to this ugly type class, or whether this is the
proper way forward. Either is fine, really, it would just be nice to
know for certain.

Thanks in advance,

More information about the Haskell-Cafe mailing list