uncertain/
boxed.rs

1use crate::{Rng, Uncertain};
2use std::boxed::Box;
3
4/// An opaque uncertain value.
5///
6/// This is useful when you need to conditionally return different uncertain values.
7/// See [`into_boxed`](Uncertain::into_boxed).
8pub struct BoxedUncertain<T> {
9    ptr: Box<dyn Uncertain<Value = T> + Send>,
10}
11
12impl<T> BoxedUncertain<T> {
13    pub(crate) fn new<U>(contained: U) -> Self
14    where
15        U: 'static + Uncertain<Value = T> + Send,
16    {
17        Self {
18            ptr: Box::new(contained),
19        }
20    }
21}
22
23impl<T> Uncertain for BoxedUncertain<T> {
24    type Value = T;
25
26    fn sample(&self, rng: &mut Rng, epoch: usize) -> Self::Value {
27        self.ptr.sample(rng, epoch)
28    }
29}
30
31#[cfg(test)]
32mod tests {
33    use crate::{Distribution, Uncertain};
34    use rand_distr::{Bernoulli, Exp1, StandardNormal};
35
36    #[test]
37    fn boxed_uncertain_allows_mixed_sources() {
38        let choice = Distribution::from(Bernoulli::new(0.5).unwrap());
39        let value = choice.flat_map(|choice| {
40            if choice {
41                Distribution::from(Exp1).into_boxed()
42            } else {
43                Distribution::from(StandardNormal).into_boxed()
44            }
45        });
46
47        assert!(value.map(|v: f32| v < 2.0).pr(0.9));
48    }
49
50    #[test]
51    fn boxed_works_with_into_ref() {
52        let x = Distribution::from(Bernoulli::new(0.5).unwrap())
53            .into_ref()
54            .into_boxed();
55        assert!(x.pr(0.5));
56    }
57}