Why the biggest take away from Tagless Final has been the type class abstraction, I am kinda confused now. Anyway.
I thought I couldn't enforce types in the operators. That is wrong. I just cannot enforce types in the operators as confined in a trait. That's where the Higher-Kinded Type is useful.
#![allow(dead_code)]
#![allow(non_snake_case)]
/*
let varZ env = fst env
let varS vp env = vp (snd env)
let b (bv:bool) env = bv
let lam e env = fun x -> e (x,env)
let app e1 e2 env = (e1 env) (e2 env)
*/
type Func<T, O> = Box<dyn FnOnce(T) -> O>;
fn varZ<A, B>() -> Func<(A, B), A> {
Box::new(|env| env.0)
}
fn varS<A, T1: 'static, T2: 'static>(vp: Func<T1, T2>) -> Func<(A, T1), T2> {
Box::new(move |env| vp(env.1))
}
fn b<P>(bv: bool) -> Func<P, bool> {
Box::new(move |_env| bv)
}
fn lam<A: 'static, B: 'static, T: 'static>(e: Func<(A, B), T>) -> Func<B, Func<A, T>> {
Box::new(|env| Box::new(|x| e((x, env))))
}
fn app<T1: 'static + Copy, T2: 'static, T3: 'static>(
e1: Func<T1, Func<T2, T3>>,
e2: Func<T1, T2>,
) -> Func<T1, T3> {
Box::new(|env| e1(env)(e2(env)))
}
fn main() {
let testf1 = app(lam(varZ()), b(true));
println!("{}", testf1(()));
let testf3 = app(lam(varS(varZ())), b(true));
println!("{}", testf3((1, (2))));
}
Top comments (0)