Is it possible to implement untyped lambda calculus using generics?

Consider the following implementation of untyped lambda calculus:

pub enum Term {
    Var(usize), // a variable with a De Bruijn index
    Abs(Box<Term>), // an abstraction
    App(Box<Term>, Box<Term>) // an application
}

impl Term {
    ...
}

I feel that this design, while simple and concise, can be useful in translating into features. Different terms should have different sets of methods, for example. only abstractions should be "unabstractable" and only applications should be evaluated.

I know the usual arguments in enums vs. traits; even if listings are the best choice here, I still want to know if this is possible.

My basic building blocks so far more or less look like this:

#[derive(Clone, PartialEq, Eq)]
pub struct Var(usize);

#[derive(Clone, PartialEq, Eq)]
pub struct Abs<T: Term>(T);

#[derive(Clone, PartialEq, Eq)]
pub struct App<T: Term, U: Term>(T, U);

pub trait Term: Clone {
    fn abs(self) -> Abs<Self> { Abs(self) }

    fn app<T: Term>(self, other: T) -> App<Self, T> { App(self, other) }

    fn update_free_variables(&mut self, added_depth: usize, own_depth: usize);

    fn _apply<T: Term>(&mut self, other: &mut T, depth: usize); // this is a helper function that enables term tree traversal for Abs<T>::apply

    fn is_reducible(&self, limit: usize, count: &usize) -> bool;

    fn beta_reduce(&mut self, order: Order, limit: usize, verbose: bool) -> usize;
}

impl Var {
    pub fn new(index: usize) -> Self {
        assert!(index > 0);
        Var(index)
    }
}

impl<T: Term> Abs<T> {
    fn unabs(self) -> T {
        self.0
    }

    fn apply<U: Term>(mut self, other: &mut U) -> T {
        self._apply(other, 0);
        self.unabs()
    }
}

impl<T: Term, U: Term> App<T, U> {
    fn unapp(self) -> (T, U) {
        (self.0, self.1)
    }
}

// and some impl Term for X

Although it is fairly easy to implement the basic functions, there are several places where I struggle to find the right solution. I need to do the following:

  • , , ,
  • ( )
  • ( , , , , )

, . enum? , ( , unsafe ..)?

+4
1

, . "unabstractable", .

, . , , . , , . , , , enum.

, . Term, , .

, , - .

, , ,

, . , , , :

To read one term, given a mutable reference to a variable stack (which begins empty):
    If the next character is an opening parenthesis:
        Consume it.
        Read a term.
        Read a term.
        Make sure the next character is a closing parenthesis, and consume it.
        Return an application of the two terms.
    If the next character is a lambda:
        Consume it.
        Make sure the next character is a variable, then consume it.
        Make sure the next character is a dot, and consume it.
        Push the variable to the variable stack.
        Read a term.
        Pop the variable off of the stack.
        Return an abstraction of the term.
    If the next character is a variable:
        Consume it.
        Search the variable stack find the first index of the variable from the top.
        Return a variable term with this index.

, -, (a b c) ((a b) c). λx.λy.λz.((x z) (y z)), λx.λy.λz.x z (y z).

( )

, , , - , , , . , , . , , , , , , , , , , . , . , , 1 .

, Term :

fn substitute(&mut self, variable_number: usize, other: &Term);

, , :

λn.λf.λx.(f ((n f) x))Abs(Abs(Abs(App(Var(1),App(App(Var(2),Var(1)),Var(0))))))

( , , , , )

, . Term, , Abs, , 0. , App, , . , - , , , , .

, -. , , , -.

, , , . enum, , .

+2

Source: https://habr.com/ru/post/1688167/


All Articles