Re: Problem applying generics to my code. Is there a better solution?
How about this:
public static <T, P> Distribution<P> posterior(List<Double> data,
NormalDistribution<T> likelihood, NormalDistribution<P> prior)
{
return normalNormalPosterior(data, likelihood, prior );
}
public static <T, P> Distribution<P> posterior(List<Integer> data,
PoissonDistribution<T> likelihood, GammaDistribution<P> prior)
{
return normalNormalPosterior(data, likelihood, prior);
}
Why have one method that does two things?
Oops. That was a typo on my part. That code path should be
public static <T, P> Distribution<P> posterior(List<Integer> data,
PoissonDistribution<T> likelihood, GammaDistribution<P> prior)
{
return poissonGammaPosterior(data, likelihood, prior);
}
You might even want to make PoissonDistribution implement a method
posterior which takes a List<Integer> data, GammaDistribution<P>
prior), and likewise on the NormalDistribution.
My motivation for the original choice was that, as a user of the
package, I want to manipulate generic Distribution<T> objects and let
the library decide if there is an efficient way of giving a
posterior. There are always numerical methods to fall back on. Also,
there can be multiple conjugate priors for the same likelihood.
Here's an example of how I want to interface to these methods
import static my.package.Conjugate.*;
public static void foo()
{
Distribution<Double> distn1 = new NormalDistribution( mu, sigma );
Distribution<Double> distn2 = new NormalDistribution( 0, tau );
Distribution<Double> post = posterior( distn1, distn2 );
}
So, the underlying problem I'm trying to solve is to dispatch based on
the most specific type of the object. Per your suggestion, I could
get around this by adding a posterior() method that would be
implemented along the lines of
public class NormalDistribution implements Distribution<Double>
{
public Distribution<Double> posterior( List<Double> data,
Distribution<Double> prior )
{
if ( prior instanceof NormalDistibution ) return
normalNormalPosterior( data, this, prior );
if ( prior instanceof GammaDistribution ) return
normalGammaPosterior( data, this, prior );
}
}
or should I just create separate methods for each type of supported
prior distribution and force the caller to call the posterior() method
with an concrete type and not the generic Distribution<> type?
I'm going to ramble on a bit here and point out that the library have
a ConditionalDistribution class which would probably be the most
appropriate vehicle for your suggestion since a NormalDistribution
class itself does not have any unbound parameters. To replicate the
last example
public class NormalDistributionWithUnknownMean extends
NormalDistribution implements ConditionalDistribution<Double, Double>
{
public NormalDistribution conjugate( List<Double> data,
NormalDistribution prior )
{
return normalNormalPosterior( data, this, prior );
}
}
public class NormalDistributionWithUnknownVariance extends
NormalDistribution implements ConditionalDistribution<Double, Double>
{
public NormalDistribution conjugate( List<Double> data,
GammaDistribution prior )
{
return normalGammaPosterior( data, this, prior );
}
}
Thank you for the discussion.