Problem applying generics to my code. Is there a better solution?



All,

I am working on a statistical inference library and have run into a
limiting case of using generics for type safety. I hope someone is
able to suggest a more elegant solution to my problem that I currently
have.

I have a small class of static methods for computing closed-form
posterior distributions. The skeleton of the classes look like this

// This class defines a distribution over a type T. Usually Integer
or Double.
public interface Distribution<T> { ... }

// Here are some probability distributions
public class NormalDistribution implements Distribution<Double>
{ ... }
public class GammaDistribution implements Distribution<Double> { ... }
public class PoissonDistribution implements Distribution<Integer>
{ ... }

// and here are a bunch of methods to compute closed form solutions to
the posteriors
public class Posteriors {
public static NormalDistribution
normalNormalPosterior( List<Double> data, NormalDistribution
likelihood, NormalDistribution prior ) { ... }
public static GammaDistribution
poissonGammaPosterior( List<Integer> data, PoissonDistribution
likelihood, GammaDistribution prior ) { ... }
}


Now, I would like to create a generic dispatch method that I can pass
any data, likelihood and prior into and it will dispatch to the
appropriate method if it exists. The prototype looks like this

public static <T, P> Distribution<P> posterior( List<T> data,
Distribution<T> likelihood, Distribution<P> prior)

So, for type safety, I want to require that the data is compatible
with the likelihood distribution and that the posterior distribution
has the same domain as the prior -- the definition of a conjugate
prior. The problem comes in the implementation. Currently, my method
looks like this

public static <T, P> Distribution<P> posterior( List<T> data,
Distribution<T> likelihood, Distribution<P> prior)
{
if ( likelihood instanceof NormalDistribution && prior instanceof
NormalDistribution )
return (Distribution<P>) normalNormalPosterior((List<Double>)
data, (NormalDistribution) likelihood, (NormalDistribution) prior );

if ( likelihood instanceof PoissonDistribution && prior instanceof
GammaDistribution )
return (Distribution<P>) normalNormalPosterior((List<Integer>)
data, (PoissonDistribution) likelihood, (GammaDistribution) prior );

throw new UnsupportedConjugatePairException();
}

This works and, logically, I don't think I can run into any strange
run-time exceptions since, for example

1. "likelihood instanceof NormalDistribution" implies that List<T>
must be a List<Double>
2. "prior instanceof NormalDistribution" ensures that the posterior
will match the prior

The real question: Is there a way to write my posterior() method
without all the ugly casting and compiler warnings?

.



Relevant Pages