I've made some adjustments to the code you've posted. Mainly I've changed the return type of new
(see explanation here as to why this is necessary). I've also changed CFMM
to MM
in the struct creation of new
, it seems like that was a typo.
Short version for the impatient: you can't return Self
from new
and put a closure in it. The compiler will tell you that
every closure has a distinct type and so could not always match the caller-chosen type of parameter F
if you attempt to do this. The key element here is "caller-chosen". Rust cannot guarantee that the closure we're constructing in new
will match whatever the caller decides F
should be. As soon as you make new
decide explicitly what it will return impl Fn(...)
it works.
There's some more explanation available here as well.
pub struct MM<F: Fn(&f64, &f64) -> f64> {
pub n: f64,
pub y: f64,
pub p: f64, // the p parameter associated with prior probability
pub f: F, // this must only take two arguments
}
pub fn new_mm(l: f64, prior: f64) -> MM<impl Fn(&f64, &f64) -> f64> {
let func = move |a: &f64, b: &f64| -> f64 { b.powf(prior) * a };
MM {
n: l,
y: l,
p: prior,
f: func,
}
}
fn main() {
let a: f64 = 1.0;
let b: f64 = 0.9;
let p = new_mm(a, b);
println!("{}", (p.f)(&1.0, &2.0));
}
Playground