computation_types/
black_box.rs1use core::fmt;
2use std::marker::PhantomData;
3
4use crate::{impl_core_ops, Computation, ComputationFn, NamedArgs, Names};
5
6#[derive(Clone, Copy, Debug)]
8pub struct BlackBox<A, F, FDim, FItem>
9where
10 Self: Computation,
11{
12 pub child: A,
13 pub f: F,
14 pub(super) f_dim: PhantomData<FDim>,
15 pub(super) f_item: PhantomData<FItem>,
16}
17
18impl<A, F, FDim, FItem> BlackBox<A, F, FDim, FItem>
19where
20 Self: Computation,
21{
22 pub fn new(child: A, f: F) -> Self {
23 Self {
24 child,
25 f,
26 f_dim: PhantomData,
27 f_item: PhantomData,
28 }
29 }
30}
31
32impl<A, F, FDim, FItem> Computation for BlackBox<A, F, FDim, FItem>
33where
34 A: Computation,
35{
36 type Dim = FDim;
37 type Item = FItem;
38}
39
40impl<A, F, FDim, FItem> ComputationFn for BlackBox<A, F, FDim, FItem>
41where
42 Self: Computation,
43 A: ComputationFn,
44 BlackBox<A::Filled, F, FDim, FItem>: Computation,
45{
46 type Filled = BlackBox<A::Filled, F, FDim, FItem>;
47
48 fn fill(self, named_args: NamedArgs) -> Self::Filled {
49 BlackBox {
50 child: self.child.fill(named_args),
51 f: self.f,
52 f_dim: self.f_dim,
53 f_item: self.f_item,
54 }
55 }
56
57 fn arg_names(&self) -> Names {
58 self.child.arg_names()
59 }
60}
61
62impl_core_ops!(BlackBox<A, F, FDim, FItem>);
63
64impl<A, F, FDim, FItem> fmt::Display for BlackBox<A, F, FDim, FItem>
65where
66 Self: Computation,
67 A: fmt::Display,
68{
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(f, "f({})", self.child)
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use proptest::prelude::*;
77 use test_strategy::proptest;
78
79 use crate::{peano::Zero, val, Computation};
80
81 #[proptest]
82 fn black_box_should_display(x: i32) {
83 let inp = val!(x);
84 prop_assert_eq!(
85 inp.black_box::<_, Zero, i32>(|x: i32| x + 1).to_string(),
86 format!("f({})", inp)
87 );
88 }
89}