pub enum Exp<T: Clone + Eq> {
Var(Ident<T>),
Abs(Ident<T>, Box<Exp<T>>),
App(Box<Exp<T>>, Box<Exp<T>>),
}Expand description
Expression in Lambda Calculus.
T represents the type of indentifiers.
Formatting:
- use
{}for simple format - use
{:#}for extra De Bruijn index information
use lambda macro to create lambda expression efficiently.
Variants§
Var(Ident<T>)
Variable identifier
Abs(Ident<T>, Box<Exp<T>>)
Abstraction
App(Box<Exp<T>>, Box<Exp<T>>)
Application
Implementations§
Source§impl<T> Exp<T>
impl<T> Exp<T>
Sourcepub fn simplify(&mut self) -> Result<&mut Self, Error>
pub fn simplify(&mut self) -> Result<&mut Self, Error>
Simplify repeatedly using beta-reduction in normal order
for at most SIMPLIFY_LIMIT times.
Examples found in repository?
5fn main() -> Result<(), Error> {
6 let zero = lambda!(s. (z. z));
7 let suc = lambda!(n. s. z. s (n s z));
8 let plus = lambda!(n. m. n {suc} m).simplify()?.to_owned();
9
10 let mut nats = vec![zero];
11 for i in 1..10 {
12 let sx = lambda!({suc} {nats[i - 1]}).simplify()?.to_owned();
13 nats.push(sx);
14 }
15
16 let sum = lambda!({plus} {nats[4]} {nats[3]}).simplify()?.to_owned();
17 assert_eq!(sum, nats[7]);
18
19 Ok(())
20}More examples
3fn main() -> Result<(), Error> {
4 // parse single expression
5 let (tt, _) = parser::parse_exp(r"\x. \y. x")?;
6
7 // parse definition statement
8 let (ident, ff, _) = parser::parse_def(r"ff = \x. \y. y")?;
9 assert_eq!(ident, "ff");
10
11 println!("ff = {}", ff);
12
13 // parse multiple definitions
14 let (map, _) = parser::parse_file(r##"
15 // and
16 and = \x. \y. x y x
17
18 // or
19 or = \x. \y. x x y
20 "##)?;
21
22 let and_t_f = lambda!({map["and"]} {tt} {ff}).simplify()?.to_owned();
23 assert_eq!(and_t_f, ff);
24
25 let or_t_f = lambda!({map["or"]} {tt} {ff}).simplify()?.to_owned();
26 assert_eq!(or_t_f, tt);
27
28 Ok(())
29}5fn main() -> Result<(), Error> {
6 // prepare some nats
7 let zero = lambda!(f. (x. x));
8 let suc = lambda!(n. f. x. f (n f x));
9 let prev = lambda!(n. f. x. n (g. h. h (g f)) (u. x) (u. u));
10 let mut nats = vec![zero];
11 for i in 1..10 {
12 let sx = lambda!({suc} {nats[i - 1]}).simplify()?.to_owned();
13 nats.push(sx);
14 assert_eq!(
15 lambda!({prev} {nats[i]}).simplify()?.to_string(),
16 nats[i - 1].to_string()
17 );
18 }
19
20 // utilities
21 let mul = lambda!(n. m. f. x. n (m f) x);
22 let if_n_is_zero = lambda!(n. n (w. x. y. y) (x. y. x));
23
24 assert_eq!(
25 lambda!({if_n_is_zero} {nats[0]} {nats[2]} {nats[1]} )
26 .simplify()?
27 .purify(),
28 nats[2].purify()
29 );
30
31 // Y combinator
32 let mut y = lambda!(f. (x. f (x x)) (x. f (x x)));
33
34 // factorial
35 let mut fact = lambda!(y. n. {if_n_is_zero} n (f. x. f x) ({mul} n (y ({prev} n))));
36
37 eprintln!("simplify fact");
38 while fact.eval_normal_order(true) {
39 eprintln!("fact = {}", fact);
40 }
41
42 let y_fact = lambda!({y} {fact});
43
44 let res = lambda!({y_fact} {nats[3]}).purify().simplify()?.to_owned();
45 eprintln!("{}", res);
46 assert_eq!(res, nats[6].purify());
47
48 // if you try to simplify Y combinator ...
49 eprintln!("simplify y: {}", y.simplify().unwrap_err()); // lamcalc::Error::SimplifyLimitExceeded
50
51 Ok(())
52}Sourcepub fn eval_normal_order(&mut self, eta_reduce: bool) -> bool
pub fn eval_normal_order(&mut self, eta_reduce: bool) -> bool
The leftmost, outermost redex is always reduced first. That is, whenever possible the arguments are substituted into the body of an abstraction before the arguments are reduced.
return false if nothing changes, otherwise true.
Examples found in repository?
5fn main() -> Result<(), Error> {
6 // prepare some nats
7 let zero = lambda!(f. (x. x));
8 let suc = lambda!(n. f. x. f (n f x));
9 let prev = lambda!(n. f. x. n (g. h. h (g f)) (u. x) (u. u));
10 let mut nats = vec![zero];
11 for i in 1..10 {
12 let sx = lambda!({suc} {nats[i - 1]}).simplify()?.to_owned();
13 nats.push(sx);
14 assert_eq!(
15 lambda!({prev} {nats[i]}).simplify()?.to_string(),
16 nats[i - 1].to_string()
17 );
18 }
19
20 // utilities
21 let mul = lambda!(n. m. f. x. n (m f) x);
22 let if_n_is_zero = lambda!(n. n (w. x. y. y) (x. y. x));
23
24 assert_eq!(
25 lambda!({if_n_is_zero} {nats[0]} {nats[2]} {nats[1]} )
26 .simplify()?
27 .purify(),
28 nats[2].purify()
29 );
30
31 // Y combinator
32 let mut y = lambda!(f. (x. f (x x)) (x. f (x x)));
33
34 // factorial
35 let mut fact = lambda!(y. n. {if_n_is_zero} n (f. x. f x) ({mul} n (y ({prev} n))));
36
37 eprintln!("simplify fact");
38 while fact.eval_normal_order(true) {
39 eprintln!("fact = {}", fact);
40 }
41
42 let y_fact = lambda!({y} {fact});
43
44 let res = lambda!({y_fact} {nats[3]}).purify().simplify()?.to_owned();
45 eprintln!("{}", res);
46 assert_eq!(res, nats[6].purify());
47
48 // if you try to simplify Y combinator ...
49 eprintln!("simplify y: {}", y.simplify().unwrap_err()); // lamcalc::Error::SimplifyLimitExceeded
50
51 Ok(())
52}Source§impl<T: Clone + Eq> Exp<T>
impl<T: Clone + Eq> Exp<T>
Sourcepub fn for_each_var<F>(&mut self, f: F)
pub fn for_each_var<F>(&mut self, f: F)
iterate over each variable
the second parameter for f is depth: number of abstractions
containing this variable.
Sourcepub fn subst_unbounded(&mut self, name: &T, exp: &Exp<T>) -> &mut Self
pub fn subst_unbounded(&mut self, name: &T, exp: &Exp<T>) -> &mut Self
Substitute free variables (de bruijn index = 0) with expression
Sourcepub fn is_beta_redex(&mut self) -> bool
pub fn is_beta_redex(&mut self) -> bool
Check whether current expression is a beta reduction.
Examples found in repository?
3fn main() {
4 let and = lambda!(x. y. (x y x));
5 let tt = lambda!(x. (y. x));
6 let ff = lambda!(x. (y. y));
7 let mut exp = lambda!({and} {tt} {ff});
8
9 eprintln!("exp = {}", exp); // ((λx. λy. (x y) x) λx. λy. x) λx. λy. y
10
11 assert!(exp.into_app().unwrap().0.is_beta_redex());
12 assert!(exp.into_app().unwrap().0.beta_reduce());
13 eprintln!("exp = {}", exp); // (λy. ((λx. λy. x) y) λx. λy. x) λx. λy. y
14
15 assert!(exp
16 .into_app()
17 .unwrap()
18 .0 // λy. ((λx. λy. x) y) λx. λy. x
19 .into_abs()
20 .unwrap()
21 .1 // ((λx. λy. x) y) λx. λy. x
22 .into_app()
23 .unwrap()
24 .0 // (λx. λy. x) y
25 .beta_reduce());
26 eprintln!("exp = {}", exp); // (λy. (λy. y) λx. λy. x) λx. λy. y
27
28 assert!(exp
29 .into_app()
30 .unwrap()
31 .0 // λy. (λy. y) λx. λy. x
32 .into_abs()
33 .unwrap()
34 .1 // (λy. y) λx. λy. x
35 .beta_reduce());
36 eprintln!("exp = {}", exp); // (λy. y) λx. λy. y
37
38 assert!(exp.beta_reduce());
39 eprintln!("exp = {}", exp); // λx. λy. y
40}Sourcepub fn beta_reduce(&mut self) -> bool
pub fn beta_reduce(&mut self) -> bool
Try making beta reduction, return false if nothing changed.
Examples found in repository?
3fn main() {
4 let and = lambda!(x. y. (x y x));
5 let tt = lambda!(x. (y. x));
6 let ff = lambda!(x. (y. y));
7 let mut exp = lambda!({and} {tt} {ff});
8
9 eprintln!("exp = {}", exp); // ((λx. λy. (x y) x) λx. λy. x) λx. λy. y
10
11 assert!(exp.into_app().unwrap().0.is_beta_redex());
12 assert!(exp.into_app().unwrap().0.beta_reduce());
13 eprintln!("exp = {}", exp); // (λy. ((λx. λy. x) y) λx. λy. x) λx. λy. y
14
15 assert!(exp
16 .into_app()
17 .unwrap()
18 .0 // λy. ((λx. λy. x) y) λx. λy. x
19 .into_abs()
20 .unwrap()
21 .1 // ((λx. λy. x) y) λx. λy. x
22 .into_app()
23 .unwrap()
24 .0 // (λx. λy. x) y
25 .beta_reduce());
26 eprintln!("exp = {}", exp); // (λy. (λy. y) λx. λy. x) λx. λy. y
27
28 assert!(exp
29 .into_app()
30 .unwrap()
31 .0 // λy. (λy. y) λx. λy. x
32 .into_abs()
33 .unwrap()
34 .1 // (λy. y) λx. λy. x
35 .beta_reduce());
36 eprintln!("exp = {}", exp); // (λy. y) λx. λy. y
37
38 assert!(exp.beta_reduce());
39 eprintln!("exp = {}", exp); // λx. λy. y
40}Sourcepub fn is_eta_redex(&mut self) -> bool
pub fn is_eta_redex(&mut self) -> bool
Check whether current expression is a eta reduction.
Examples found in repository?
3fn main() {
4 let mut exp = lambda!(a. b. c. f a b c);
5
6 eprintln!("exp = {}", exp);
7 assert!(exp
8 .into_abs()
9 .unwrap()
10 .1
11 .into_abs()
12 .unwrap()
13 .1
14 .is_eta_redex());
15
16 assert!(exp.into_abs().unwrap().1.into_abs().unwrap().1.eta_reduce());
17 eprintln!("exp = {}", exp);
18
19 assert!(exp.into_abs().unwrap().1.eta_reduce());
20 eprintln!("exp = {}", exp);
21
22 assert!(exp.eta_reduce());
23 eprintln!("exp = {}", exp);
24}Sourcepub fn eta_reduce(&mut self) -> bool
pub fn eta_reduce(&mut self) -> bool
Eta reduce requires the function’s extensionality axiom, thus is not enabled by default.
Examples found in repository?
3fn main() {
4 let mut exp = lambda!(a. b. c. f a b c);
5
6 eprintln!("exp = {}", exp);
7 assert!(exp
8 .into_abs()
9 .unwrap()
10 .1
11 .into_abs()
12 .unwrap()
13 .1
14 .is_eta_redex());
15
16 assert!(exp.into_abs().unwrap().1.into_abs().unwrap().1.eta_reduce());
17 eprintln!("exp = {}", exp);
18
19 assert!(exp.into_abs().unwrap().1.eta_reduce());
20 eprintln!("exp = {}", exp);
21
22 assert!(exp.eta_reduce());
23 eprintln!("exp = {}", exp);
24}Sourcepub fn purify(&self) -> Exp<()>
pub fn purify(&self) -> Exp<()>
Remove name of indentifiers, keeping just de bruijn code. If there are free variables, they will become the same thing.
Examples found in repository?
5fn main() -> Result<(), Error> {
6 // prepare some nats
7 let zero = lambda!(f. (x. x));
8 let suc = lambda!(n. f. x. f (n f x));
9 let prev = lambda!(n. f. x. n (g. h. h (g f)) (u. x) (u. u));
10 let mut nats = vec![zero];
11 for i in 1..10 {
12 let sx = lambda!({suc} {nats[i - 1]}).simplify()?.to_owned();
13 nats.push(sx);
14 assert_eq!(
15 lambda!({prev} {nats[i]}).simplify()?.to_string(),
16 nats[i - 1].to_string()
17 );
18 }
19
20 // utilities
21 let mul = lambda!(n. m. f. x. n (m f) x);
22 let if_n_is_zero = lambda!(n. n (w. x. y. y) (x. y. x));
23
24 assert_eq!(
25 lambda!({if_n_is_zero} {nats[0]} {nats[2]} {nats[1]} )
26 .simplify()?
27 .purify(),
28 nats[2].purify()
29 );
30
31 // Y combinator
32 let mut y = lambda!(f. (x. f (x x)) (x. f (x x)));
33
34 // factorial
35 let mut fact = lambda!(y. n. {if_n_is_zero} n (f. x. f x) ({mul} n (y ({prev} n))));
36
37 eprintln!("simplify fact");
38 while fact.eval_normal_order(true) {
39 eprintln!("fact = {}", fact);
40 }
41
42 let y_fact = lambda!({y} {fact});
43
44 let res = lambda!({y_fact} {nats[3]}).purify().simplify()?.to_owned();
45 eprintln!("{}", res);
46 assert_eq!(res, nats[6].purify());
47
48 // if you try to simplify Y combinator ...
49 eprintln!("simplify y: {}", y.simplify().unwrap_err()); // lamcalc::Error::SimplifyLimitExceeded
50
51 Ok(())
52}Sourcepub fn into_app(&mut self) -> Option<(&mut Self, &mut Self)>
pub fn into_app(&mut self) -> Option<(&mut Self, &mut Self)>
return func and body for App.
Examples found in repository?
3fn main() {
4 let and = lambda!(x. y. (x y x));
5 let tt = lambda!(x. (y. x));
6 let ff = lambda!(x. (y. y));
7 let mut exp = lambda!({and} {tt} {ff});
8
9 eprintln!("exp = {}", exp); // ((λx. λy. (x y) x) λx. λy. x) λx. λy. y
10
11 assert!(exp.into_app().unwrap().0.is_beta_redex());
12 assert!(exp.into_app().unwrap().0.beta_reduce());
13 eprintln!("exp = {}", exp); // (λy. ((λx. λy. x) y) λx. λy. x) λx. λy. y
14
15 assert!(exp
16 .into_app()
17 .unwrap()
18 .0 // λy. ((λx. λy. x) y) λx. λy. x
19 .into_abs()
20 .unwrap()
21 .1 // ((λx. λy. x) y) λx. λy. x
22 .into_app()
23 .unwrap()
24 .0 // (λx. λy. x) y
25 .beta_reduce());
26 eprintln!("exp = {}", exp); // (λy. (λy. y) λx. λy. x) λx. λy. y
27
28 assert!(exp
29 .into_app()
30 .unwrap()
31 .0 // λy. (λy. y) λx. λy. x
32 .into_abs()
33 .unwrap()
34 .1 // (λy. y) λx. λy. x
35 .beta_reduce());
36 eprintln!("exp = {}", exp); // (λy. y) λx. λy. y
37
38 assert!(exp.beta_reduce());
39 eprintln!("exp = {}", exp); // λx. λy. y
40}Sourcepub fn into_abs(&mut self) -> Option<(&mut Ident<T>, &mut Self)>
pub fn into_abs(&mut self) -> Option<(&mut Ident<T>, &mut Self)>
return body for Abs.
Examples found in repository?
3fn main() {
4 let mut exp = lambda!(a. b. c. f a b c);
5
6 eprintln!("exp = {}", exp);
7 assert!(exp
8 .into_abs()
9 .unwrap()
10 .1
11 .into_abs()
12 .unwrap()
13 .1
14 .is_eta_redex());
15
16 assert!(exp.into_abs().unwrap().1.into_abs().unwrap().1.eta_reduce());
17 eprintln!("exp = {}", exp);
18
19 assert!(exp.into_abs().unwrap().1.eta_reduce());
20 eprintln!("exp = {}", exp);
21
22 assert!(exp.eta_reduce());
23 eprintln!("exp = {}", exp);
24}More examples
3fn main() {
4 let and = lambda!(x. y. (x y x));
5 let tt = lambda!(x. (y. x));
6 let ff = lambda!(x. (y. y));
7 let mut exp = lambda!({and} {tt} {ff});
8
9 eprintln!("exp = {}", exp); // ((λx. λy. (x y) x) λx. λy. x) λx. λy. y
10
11 assert!(exp.into_app().unwrap().0.is_beta_redex());
12 assert!(exp.into_app().unwrap().0.beta_reduce());
13 eprintln!("exp = {}", exp); // (λy. ((λx. λy. x) y) λx. λy. x) λx. λy. y
14
15 assert!(exp
16 .into_app()
17 .unwrap()
18 .0 // λy. ((λx. λy. x) y) λx. λy. x
19 .into_abs()
20 .unwrap()
21 .1 // ((λx. λy. x) y) λx. λy. x
22 .into_app()
23 .unwrap()
24 .0 // (λx. λy. x) y
25 .beta_reduce());
26 eprintln!("exp = {}", exp); // (λy. (λy. y) λx. λy. x) λx. λy. y
27
28 assert!(exp
29 .into_app()
30 .unwrap()
31 .0 // λy. (λy. y) λx. λy. x
32 .into_abs()
33 .unwrap()
34 .1 // (λy. y) λx. λy. x
35 .beta_reduce());
36 eprintln!("exp = {}", exp); // (λy. y) λx. λy. y
37
38 assert!(exp.beta_reduce());
39 eprintln!("exp = {}", exp); // λx. λy. y
40}Sourcepub fn into_ident(&mut self) -> Option<&mut Ident<T>>
pub fn into_ident(&mut self) -> Option<&mut Ident<T>>
return identifer for Var.