So I have a struct WeatherStation which consists of a name: String and probability distribution function which should implement the rand::distr::Distribution trait. It look something like this:
struct WeatherStation<'a, D> {
name: &'a str,
distribution: D,
}
I also have 2 methods on that struct:
impl<'a, D> WeatherStation<'a, D> {
fn new(name: &'a str, distribution: D) -> Self {
Self {
name,
distribution,
_marker: PhantomData
}
}
fn measurement<T>(&self) -> T
where
T: Float,
D: Distribution<T>
{
self.distribution.sample(&mut rand::rng())
}
}
My question is how should I best enforce these trait bounds.
Here are my ideas:
- Idea 1 (doesn't enforce Distribution trait in
newmethod):struct WeatherStation<'a, D> { name: &'a str, distribution: D, } impl<'a, D> WeatherStation<'a, D> { fn new(name: &'a str, distribution: D) -> Self { Self { name, distribution, } } fn measurement<T>(&self) -> T where T: Float, D: Distribution<T> { self.distribution.sample(&mut rand::rng()) } } - Idea 1.1 (code repetition, T of new != T of measurement):
struct WeatherStation<'a, D> { name: &'a str, distribution: D, } impl<'a, D> WeatherStation<'a, D> { fn new<T>(name: &'a str, distribution: D) -> Self where T: Float, D: Distribution<T> { Self { name, distribution, } } fn measurement<T>(&self) -> T where T: Float, D: Distribution<T> { self.distribution.sample(&mut rand::rng()) } } - Idea 2 (requires
PhatomData, no relationship between D and T in struct):struct WeatherStation<'a, D, T> { name: &'a str, distribution: D, _marker: PhantomData<T> } impl<'a, D, T> WeatherStation<'a, D, T> where D: Distribution<T>, T: Float { fn new(name: &'a str, distribution: D) -> Self { Self { name, distribution, _marker: PhantomData } } fn measurement(&self) -> T { self.distribution.sample(&mut rand::rng()) } }
Which one of these should I use and why? Is there a more idiomatic way to do this?