0

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 new method):
    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?

2
  • 1
    Does this answer your question? Should trait bounds be duplicated in struct and impl? Commented Jun 23 at 17:06
  • Somewhat. So I shouldn't put trait bounds on the struct itself but should I force the Distribution crate on the new method and should i use PhantomData or not? Commented Jun 23 at 17:17

1 Answer 1

2

Your "idea 1" is the most idiomatic Rust. Note in particular that the standard library takes this approach -- for example, HashMap::new does not require any particular bounds, but anything that could actually fetch/insert will require K: Hash + Eq.

As far as whether T should be part of the type, that ultimately depends on factors not apparent from your question. For example, if you are relying on a specific WeatherStation instantiation to convey information about the type of the distribution that should be used in all cases, then you could do this (though I would use PhantomData<fn() -> T> as this helps the borrow checker know that your type doesn't actually contain a T). You could also need to do this in particular trait implementation scenarios, where you need to add another type to be able to differentiate blanket impls.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.