Exp

Enum Exp 

Source
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>
where T: Clone + Eq,

Source

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?
examples/church_encoding.rs (line 8)
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
Hide additional examples
examples/parser.rs (line 22)
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}
examples/y_combinator.rs (line 12)
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

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?
examples/y_combinator.rs (line 38)
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>

Source

pub fn for_each_var<F>(&mut self, f: F)
where F: Fn(&mut Exp<T>, u32) + Clone,

iterate over each variable the second parameter for f is depth: number of abstractions containing this variable.

Source

pub fn subst_unbounded(&mut self, name: &T, exp: &Exp<T>) -> &mut Self

Substitute free variables (de bruijn index = 0) with expression

Source

pub fn is_beta_redex(&mut self) -> bool

Check whether current expression is a beta reduction.

Examples found in repository?
examples/beta_reduce.rs (line 11)
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}
Source

pub fn beta_reduce(&mut self) -> bool

Try making beta reduction, return false if nothing changed.

Examples found in repository?
examples/beta_reduce.rs (line 12)
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}
Source

pub fn is_eta_redex(&mut self) -> bool

Check whether current expression is a eta reduction.

Examples found in repository?
examples/eta_reduce.rs (line 14)
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}
Source

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?
examples/eta_reduce.rs (line 16)
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}
Source

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?
examples/y_combinator.rs (line 27)
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

pub fn into_app(&mut self) -> Option<(&mut Self, &mut Self)>

return func and body for App.

Examples found in repository?
examples/beta_reduce.rs (line 11)
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}
Source

pub fn into_abs(&mut self) -> Option<(&mut Ident<T>, &mut Self)>

return body for Abs.

Examples found in repository?
examples/eta_reduce.rs (line 8)
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
Hide additional examples
examples/beta_reduce.rs (line 19)
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}
Source

pub fn into_ident(&mut self) -> Option<&mut Ident<T>>

return identifer for Var.

Trait Implementations§

Source§

impl<T: Clone + Clone + Eq> Clone for Exp<T>

Source§

fn clone(&self) -> Exp<T>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug + Clone + Eq> Debug for Exp<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Exp<()>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Exp<String>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: PartialEq + Clone + Eq> PartialEq for Exp<T>

Source§

fn eq(&self, other: &Exp<T>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<T: Eq + Clone + Eq> Eq for Exp<T>

Source§

impl<T: Clone + Eq> StructuralPartialEq for Exp<T>

Auto Trait Implementations§

§

impl<T> Freeze for Exp<T>
where T: Freeze,

§

impl<T> RefUnwindSafe for Exp<T>
where T: RefUnwindSafe,

§

impl<T> Send for Exp<T>
where T: Send,

§

impl<T> Sync for Exp<T>
where T: Sync,

§

impl<T> Unpin for Exp<T>
where T: Unpin,

§

impl<T> UnwindSafe for Exp<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.