"need a Monad" sounds scary but in practice it looks like this
impl<T> Secret<T> { pub fn map<U>(&self, func: impl FnOnce(&T) -> U) -> Secret<U> { Secret(func(&self.0)) } pub fn flat_map<U>(&self, func: impl FnOnce(&T) -> Secret<U>) -> Secret<U> { func(&self.0) } }
impl<T> Secret<T> { pub unsafe fn reveal(&self) -> &T { &self.0 } }
func(param1: A, param2: B) -> C
flat_map(secret1, |param1| map(secret2, |param2| func(param1, param2) ) )
do! { param1 <- secret1; param2 <- secret2; Secret(func(param1, param2)); }
func(secret1, secret2)
"need a Monad" sounds scary but in practice it looks like this
If you need an escape hatch for something more complicated, you could provide an api to that