Bind

Struct Bind 

Source
pub struct Bind<P, T> { /* private fields */ }
Expand description

A binding construct that binds a name within a term

Implementations§

Source§

impl<P, T> Bind<P, T>

Source

pub fn new(pattern: P, body: T) -> Self

Create a new binding

Examples found in repository?
examples/system_f.rs (lines 50-53)
36    fn subst(&self, var: &Name<Ty>, value: &Ty) -> Self {
37        match self {
38            Ty::TyVar(v) if v == var => value.clone(),
39            Ty::TyVar(v) => Ty::TyVar(v.clone()),
40            Ty::Arr(t1, t2) => Ty::Arr(
41                Box::new((**t1).subst(var, value)),
42                Box::new((**t2).subst(var, value)),
43            ),
44            Ty::All(bnd) => {
45                let vars = bnd.pattern();
46                if vars.iter().any(|v| v == var) {
47                    // Variable is bound, no substitution
48                    self.clone()
49                } else {
50                    Ty::All(Bind::new(
51                        vars.clone(),
52                        Box::new((**bnd.body()).subst(var, value)),
53                    ))
54                }
55            }
56        }
57    }
58}
59
60// Subst Tm Ty - terms don't substitute into types
61impl Subst<Tm> for Ty {
62    fn is_var(&self) -> Option<SubstName<Tm>> {
63        None
64    }
65
66    fn subst(&self, _var: &Name<Tm>, _value: &Tm) -> Self {
67        self.clone()
68    }
69}
70
71impl Ty {
72    fn tyvar(name: TyName) -> Ty {
73        Ty::TyVar(name)
74    }
75
76    fn arr(t1: Ty, t2: Ty) -> Ty {
77        Ty::Arr(Box::new(t1), Box::new(t2))
78    }
79
80    fn forall(vars: Vec<TyName>, ty: Ty) -> Ty {
81        Ty::All(bind(vars, Box::new(ty)))
82    }
83}
84
85impl fmt::Display for Ty {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        match self {
88            Ty::TyVar(a) => write!(f, "{}", a),
89            Ty::Arr(t1, t2) => write!(f, "({} → {})", t1, t2),
90            Ty::All(bnd) => {
91                let vars = bnd.pattern();
92                write!(f, "∀")?;
93                for (i, v) in vars.iter().enumerate() {
94                    if i > 0 {
95                        write!(f, " ")?;
96                    }
97                    write!(f, "{}", v)?;
98                }
99                write!(f, ". {}", bnd.body())
100            }
101        }
102    }
103}
104
105/// Embedded type annotation
106#[derive(Clone, Debug, PartialEq)]
107struct Embed<T>(T);
108
109impl<T: Alpha> Alpha for Embed<T> {
110    fn aeq(&self, other: &Self) -> bool {
111        self.0.aeq(&other.0)
112    }
113
114    fn aeq_in(&self, ctx: &mut AlphaCtx, other: &Self) -> bool {
115        self.0.aeq_in(ctx, &other.0)
116    }
117
118    fn fv_in(&self, vars: &mut Vec<String>) {
119        self.0.fv_in(vars)
120    }
121}
122
123impl<T: Subst<V>, V> Subst<V> for Embed<T> {
124    fn is_var(&self) -> Option<SubstName<V>> {
125        None
126    }
127
128    fn subst(&self, var: &Name<V>, value: &V) -> Self {
129        Embed(self.0.subst(var, value))
130    }
131}
132
133/// System F terms
134#[derive(Clone, Debug, Alpha)]
135#[allow(dead_code)]
136enum Tm {
137    /// Term variables
138    TmVar(TmName),
139    /// Term abstraction (lambda)
140    Lam(Bind<(TmName, Embed<Ty>), Box<Tm>>),
141    /// Type abstraction (big lambda)
142    TLam(Bind<Vec<TyName>, Box<Tm>>),
143    /// Term application
144    App(Box<Tm>, Box<Tm>),
145    /// Type application
146    TApp(Box<Tm>, Vec<Ty>),
147}
148
149// Only need to specify when it's a variable for Subst<Tm>
150impl Subst<Tm> for Tm {
151    fn is_var(&self) -> Option<SubstName<Tm>> {
152        match self {
153            Tm::TmVar(v) => Some(SubstName::Name(v.clone())),
154            _ => None,
155        }
156    }
157
158    fn subst(&self, var: &Name<Tm>, value: &Tm) -> Self {
159        match self {
160            Tm::TmVar(v) if v == var => value.clone(),
161            Tm::TmVar(v) => Tm::TmVar(v.clone()),
162            Tm::Lam(b) => {
163                let (x, ann) = b.pattern();
164                if x == var {
165                    // Variable is bound, no substitution
166                    self.clone()
167                } else {
168                    // Substitute in body
169                    Tm::Lam(Bind::new(
170                        (x.clone(), ann.clone()),
171                        Box::new((**b.body()).subst(var, value)),
172                    ))
173                }
174            }
175            Tm::TLam(b) => {
176                // Type variables can't capture term variables, so substitute in body
177                Tm::TLam(Bind::new(
178                    b.pattern().clone(),
179                    Box::new((**b.body()).subst(var, value)),
180                ))
181            }
182            Tm::App(e1, e2) => Tm::App(
183                Box::new((**e1).subst(var, value)),
184                Box::new((**e2).subst(var, value)),
185            ),
186            Tm::TApp(t, tys) => Tm::TApp(Box::new((**t).subst(var, value)), tys.clone()),
187        }
188    }
189}
190
191// Subst Ty Tm - substituting types in terms
192impl Subst<Ty> for Tm {
193    fn is_var(&self) -> Option<SubstName<Ty>> {
194        None // Terms never contain type variables at the term level
195    }
196
197    fn subst(&self, var: &Name<Ty>, value: &Ty) -> Self {
198        match self {
199            Tm::TmVar(x) => Tm::TmVar(x.clone()),
200            Tm::Lam(b) => {
201                let (x, Embed(ty)) = b.pattern();
202                Tm::Lam(Bind::new(
203                    (x.clone(), Embed(ty.subst(var, value))),
204                    Box::new((**b.body()).subst(var, value)),
205                ))
206            }
207            Tm::TLam(b) => {
208                let vars = b.pattern();
209                if vars.iter().any(|v| v == var) {
210                    // Type variable is bound, no substitution
211                    self.clone()
212                } else {
213                    Tm::TLam(Bind::new(
214                        vars.clone(),
215                        Box::new((**b.body()).subst(var, value)),
216                    ))
217                }
218            }
219            Tm::App(e1, e2) => Tm::App(
220                Box::new((**e1).subst(var, value)),
221                Box::new((**e2).subst(var, value)),
222            ),
223            Tm::TApp(t, tys) => Tm::TApp(
224                Box::new((**t).subst(var, value)),
225                tys.iter().map(|ty| ty.subst(var, value)).collect(),
226            ),
227        }
228    }
Source

pub fn unbind(self) -> (P, T)

Unbind a binding, returning the pattern and body This should be used within FreshM to get fresh names

Examples found in repository?
examples/system_f.rs (line 341)
327fn check_type(ctx: &Context, ty: &Ty) -> Result<(), String> {
328    match ty {
329        Ty::TyVar(a) => {
330            if ctx.lookup_type(a) {
331                Ok(())
332            } else {
333                Err(format!("Type variable {} not in scope", a))
334            }
335        }
336        Ty::Arr(t1, t2) => {
337            check_type(ctx, t1)?;
338            check_type(ctx, t2)
339        }
340        Ty::All(bnd) => {
341            let (vars, body) = bnd.clone().unbind();
342            let new_ctx = ctx.extend_type(vars);
343            check_type(&new_ctx, &body)
344        }
345    }
346}
347
348/// Type inference for terms
349fn type_infer(ctx: &Context, tm: &Tm) -> FreshM<Result<Ty, String>> {
350    match tm {
351        Tm::TmVar(x) => FreshM::pure(
352            ctx.lookup_term(x)
353                .ok_or_else(|| format!("Term variable {} not in scope", x)),
354        ),
355        Tm::Lam(bnd) => {
356            let ((x, Embed(ty)), body) = bnd.clone().unbind();
357            if let Err(e) = check_type(ctx, &ty) {
358                return FreshM::pure(Err(e));
359            }
360            let new_ctx = ctx.extend_term(x, ty.clone());
361            type_infer(&new_ctx, &body).map(|result| result.map(|body_ty| Ty::arr(ty, body_ty)))
362        }
363        Tm::TLam(bnd) => {
364            let (vars, body) = bnd.clone().unbind();
365            let new_ctx = ctx.extend_type(vars.clone());
366            type_infer(&new_ctx, &body).map(|result| result.map(|ty| Ty::forall(vars, ty)))
367        }
368        Tm::App(t1, t2) => {
369            let ctx_clone = ctx.clone();
370            let t2_clone = t2.clone();
371            type_infer(ctx, t1).and_then(move |ty1_result| match ty1_result {
372                Ok(Ty::Arr(arg_ty, ret_ty)) => {
373                    type_infer(&ctx_clone, &t2_clone).map(move |ty2_result| match ty2_result {
374                        Ok(ty2) if arg_ty.aeq(&Box::new(ty2.clone())) => Ok(*ret_ty),
375                        Ok(ty2) => Err(format!("Type mismatch: expected {}, got {}", arg_ty, ty2)),
376                        Err(e) => Err(e),
377                    })
378                }
379                Ok(ty) => FreshM::pure(Err(format!("Expected function type, got {}", ty))),
380                Err(e) => FreshM::pure(Err(e)),
381            })
382        }
383        Tm::TApp(t, tys) => {
384            // Check all type arguments are well-formed
385            for ty in tys {
386                if let Err(e) = check_type(ctx, ty) {
387                    return FreshM::pure(Err(e));
388                }
389            }
390
391            let tys_clone = tys.clone();
392            type_infer(ctx, t).map(move |ty_result| match ty_result {
393                Ok(Ty::All(bnd)) => {
394                    let (vars, body) = bnd.clone().unbind();
395                    if vars.len() != tys_clone.len() {
396                        Err(format!(
397                            "Type application arity mismatch: expected {}, got {}",
398                            vars.len(),
399                            tys_clone.len()
400                        ))
401                    } else {
402                        // Substitute type arguments
403                        let mut result = *body;
404                        for (var, ty) in vars.iter().zip(tys_clone.iter()) {
405                            result = result.subst(var, ty);
406                        }
407                        Ok(result)
408                    }
409                }
410                Ok(ty) => Err(format!("Expected polymorphic type, got {}", ty)),
411                Err(e) => Err(e),
412            })
413        }
414    }
415}
More examples
Hide additional examples
examples/lambda.rs (line 45)
41fn eval(expr: Expr) -> FreshM<Expr> {
42    match expr {
43        Expr::V(x) => FreshM::pure(Expr::V(x)),
44        Expr::Lam(bnd) => {
45            let (x, body) = bnd.unbind();
46            eval(*body).map(move |evaluated_body| Expr::Lam(bind(x, Box::new(evaluated_body))))
47        }
48        Expr::App(e1, e2) => eval(*e1.clone()).and_then(move |v1| {
49            eval(*e2.clone()).and_then(move |v2| match v1 {
50                Expr::Lam(bnd) => {
51                    let (x, body) = bnd.unbind();
52                    let substituted = body.subst(&x, &v2);
53                    eval(*substituted)
54                }
55                other => FreshM::pure(Expr::app(other, v2)),
56            })
57        }),
58    }
59}
Source

pub fn pattern(&self) -> &P

Get a reference to the pattern

Examples found in repository?
examples/system_f.rs (line 45)
36    fn subst(&self, var: &Name<Ty>, value: &Ty) -> Self {
37        match self {
38            Ty::TyVar(v) if v == var => value.clone(),
39            Ty::TyVar(v) => Ty::TyVar(v.clone()),
40            Ty::Arr(t1, t2) => Ty::Arr(
41                Box::new((**t1).subst(var, value)),
42                Box::new((**t2).subst(var, value)),
43            ),
44            Ty::All(bnd) => {
45                let vars = bnd.pattern();
46                if vars.iter().any(|v| v == var) {
47                    // Variable is bound, no substitution
48                    self.clone()
49                } else {
50                    Ty::All(Bind::new(
51                        vars.clone(),
52                        Box::new((**bnd.body()).subst(var, value)),
53                    ))
54                }
55            }
56        }
57    }
58}
59
60// Subst Tm Ty - terms don't substitute into types
61impl Subst<Tm> for Ty {
62    fn is_var(&self) -> Option<SubstName<Tm>> {
63        None
64    }
65
66    fn subst(&self, _var: &Name<Tm>, _value: &Tm) -> Self {
67        self.clone()
68    }
69}
70
71impl Ty {
72    fn tyvar(name: TyName) -> Ty {
73        Ty::TyVar(name)
74    }
75
76    fn arr(t1: Ty, t2: Ty) -> Ty {
77        Ty::Arr(Box::new(t1), Box::new(t2))
78    }
79
80    fn forall(vars: Vec<TyName>, ty: Ty) -> Ty {
81        Ty::All(bind(vars, Box::new(ty)))
82    }
83}
84
85impl fmt::Display for Ty {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        match self {
88            Ty::TyVar(a) => write!(f, "{}", a),
89            Ty::Arr(t1, t2) => write!(f, "({} → {})", t1, t2),
90            Ty::All(bnd) => {
91                let vars = bnd.pattern();
92                write!(f, "∀")?;
93                for (i, v) in vars.iter().enumerate() {
94                    if i > 0 {
95                        write!(f, " ")?;
96                    }
97                    write!(f, "{}", v)?;
98                }
99                write!(f, ". {}", bnd.body())
100            }
101        }
102    }
103}
104
105/// Embedded type annotation
106#[derive(Clone, Debug, PartialEq)]
107struct Embed<T>(T);
108
109impl<T: Alpha> Alpha for Embed<T> {
110    fn aeq(&self, other: &Self) -> bool {
111        self.0.aeq(&other.0)
112    }
113
114    fn aeq_in(&self, ctx: &mut AlphaCtx, other: &Self) -> bool {
115        self.0.aeq_in(ctx, &other.0)
116    }
117
118    fn fv_in(&self, vars: &mut Vec<String>) {
119        self.0.fv_in(vars)
120    }
121}
122
123impl<T: Subst<V>, V> Subst<V> for Embed<T> {
124    fn is_var(&self) -> Option<SubstName<V>> {
125        None
126    }
127
128    fn subst(&self, var: &Name<V>, value: &V) -> Self {
129        Embed(self.0.subst(var, value))
130    }
131}
132
133/// System F terms
134#[derive(Clone, Debug, Alpha)]
135#[allow(dead_code)]
136enum Tm {
137    /// Term variables
138    TmVar(TmName),
139    /// Term abstraction (lambda)
140    Lam(Bind<(TmName, Embed<Ty>), Box<Tm>>),
141    /// Type abstraction (big lambda)
142    TLam(Bind<Vec<TyName>, Box<Tm>>),
143    /// Term application
144    App(Box<Tm>, Box<Tm>),
145    /// Type application
146    TApp(Box<Tm>, Vec<Ty>),
147}
148
149// Only need to specify when it's a variable for Subst<Tm>
150impl Subst<Tm> for Tm {
151    fn is_var(&self) -> Option<SubstName<Tm>> {
152        match self {
153            Tm::TmVar(v) => Some(SubstName::Name(v.clone())),
154            _ => None,
155        }
156    }
157
158    fn subst(&self, var: &Name<Tm>, value: &Tm) -> Self {
159        match self {
160            Tm::TmVar(v) if v == var => value.clone(),
161            Tm::TmVar(v) => Tm::TmVar(v.clone()),
162            Tm::Lam(b) => {
163                let (x, ann) = b.pattern();
164                if x == var {
165                    // Variable is bound, no substitution
166                    self.clone()
167                } else {
168                    // Substitute in body
169                    Tm::Lam(Bind::new(
170                        (x.clone(), ann.clone()),
171                        Box::new((**b.body()).subst(var, value)),
172                    ))
173                }
174            }
175            Tm::TLam(b) => {
176                // Type variables can't capture term variables, so substitute in body
177                Tm::TLam(Bind::new(
178                    b.pattern().clone(),
179                    Box::new((**b.body()).subst(var, value)),
180                ))
181            }
182            Tm::App(e1, e2) => Tm::App(
183                Box::new((**e1).subst(var, value)),
184                Box::new((**e2).subst(var, value)),
185            ),
186            Tm::TApp(t, tys) => Tm::TApp(Box::new((**t).subst(var, value)), tys.clone()),
187        }
188    }
189}
190
191// Subst Ty Tm - substituting types in terms
192impl Subst<Ty> for Tm {
193    fn is_var(&self) -> Option<SubstName<Ty>> {
194        None // Terms never contain type variables at the term level
195    }
196
197    fn subst(&self, var: &Name<Ty>, value: &Ty) -> Self {
198        match self {
199            Tm::TmVar(x) => Tm::TmVar(x.clone()),
200            Tm::Lam(b) => {
201                let (x, Embed(ty)) = b.pattern();
202                Tm::Lam(Bind::new(
203                    (x.clone(), Embed(ty.subst(var, value))),
204                    Box::new((**b.body()).subst(var, value)),
205                ))
206            }
207            Tm::TLam(b) => {
208                let vars = b.pattern();
209                if vars.iter().any(|v| v == var) {
210                    // Type variable is bound, no substitution
211                    self.clone()
212                } else {
213                    Tm::TLam(Bind::new(
214                        vars.clone(),
215                        Box::new((**b.body()).subst(var, value)),
216                    ))
217                }
218            }
219            Tm::App(e1, e2) => Tm::App(
220                Box::new((**e1).subst(var, value)),
221                Box::new((**e2).subst(var, value)),
222            ),
223            Tm::TApp(t, tys) => Tm::TApp(
224                Box::new((**t).subst(var, value)),
225                tys.iter().map(|ty| ty.subst(var, value)).collect(),
226            ),
227        }
228    }
229}
230
231impl Tm {
232    fn var(name: TmName) -> Tm {
233        Tm::TmVar(name)
234    }
235
236    fn lam(var: TmName, ty: Ty, body: Tm) -> Tm {
237        Tm::Lam(bind((var, Embed(ty)), Box::new(body)))
238    }
239
240    fn tlam(tyvars: Vec<TyName>, body: Tm) -> Tm {
241        Tm::TLam(bind(tyvars, Box::new(body)))
242    }
243
244    #[allow(dead_code)]
245    fn app(t1: Tm, t2: Tm) -> Tm {
246        Tm::App(Box::new(t1), Box::new(t2))
247    }
248
249    fn tapp(t: Tm, tys: Vec<Ty>) -> Tm {
250        Tm::TApp(Box::new(t), tys)
251    }
252}
253
254impl fmt::Display for Tm {
255    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256        match self {
257            Tm::TmVar(x) => write!(f, "{}", x),
258            Tm::Lam(bnd) => {
259                let (x, Embed(ty)) = bnd.pattern();
260                write!(f, "λ{}:{}. ...", x, ty)
261            }
262            Tm::TLam(bnd) => {
263                let vars = bnd.pattern();
264                write!(f, "Λ")?;
265                for (i, v) in vars.iter().enumerate() {
266                    if i > 0 {
267                        write!(f, " ")?;
268                    }
269                    write!(f, "{}", v)?;
270                }
271                write!(f, ". ...")
272            }
273            Tm::App(t1, t2) => write!(f, "({} {})", t1, t2),
274            Tm::TApp(t, tys) => {
275                write!(f, "({}", t)?;
276                for ty in tys {
277                    write!(f, " [{}]", ty)?;
278                }
279                write!(f, ")")
280            }
281        }
282    }
Source

pub fn body(&self) -> &T

Get a reference to the body

Examples found in repository?
examples/system_f.rs (line 52)
36    fn subst(&self, var: &Name<Ty>, value: &Ty) -> Self {
37        match self {
38            Ty::TyVar(v) if v == var => value.clone(),
39            Ty::TyVar(v) => Ty::TyVar(v.clone()),
40            Ty::Arr(t1, t2) => Ty::Arr(
41                Box::new((**t1).subst(var, value)),
42                Box::new((**t2).subst(var, value)),
43            ),
44            Ty::All(bnd) => {
45                let vars = bnd.pattern();
46                if vars.iter().any(|v| v == var) {
47                    // Variable is bound, no substitution
48                    self.clone()
49                } else {
50                    Ty::All(Bind::new(
51                        vars.clone(),
52                        Box::new((**bnd.body()).subst(var, value)),
53                    ))
54                }
55            }
56        }
57    }
58}
59
60// Subst Tm Ty - terms don't substitute into types
61impl Subst<Tm> for Ty {
62    fn is_var(&self) -> Option<SubstName<Tm>> {
63        None
64    }
65
66    fn subst(&self, _var: &Name<Tm>, _value: &Tm) -> Self {
67        self.clone()
68    }
69}
70
71impl Ty {
72    fn tyvar(name: TyName) -> Ty {
73        Ty::TyVar(name)
74    }
75
76    fn arr(t1: Ty, t2: Ty) -> Ty {
77        Ty::Arr(Box::new(t1), Box::new(t2))
78    }
79
80    fn forall(vars: Vec<TyName>, ty: Ty) -> Ty {
81        Ty::All(bind(vars, Box::new(ty)))
82    }
83}
84
85impl fmt::Display for Ty {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        match self {
88            Ty::TyVar(a) => write!(f, "{}", a),
89            Ty::Arr(t1, t2) => write!(f, "({} → {})", t1, t2),
90            Ty::All(bnd) => {
91                let vars = bnd.pattern();
92                write!(f, "∀")?;
93                for (i, v) in vars.iter().enumerate() {
94                    if i > 0 {
95                        write!(f, " ")?;
96                    }
97                    write!(f, "{}", v)?;
98                }
99                write!(f, ". {}", bnd.body())
100            }
101        }
102    }
103}
104
105/// Embedded type annotation
106#[derive(Clone, Debug, PartialEq)]
107struct Embed<T>(T);
108
109impl<T: Alpha> Alpha for Embed<T> {
110    fn aeq(&self, other: &Self) -> bool {
111        self.0.aeq(&other.0)
112    }
113
114    fn aeq_in(&self, ctx: &mut AlphaCtx, other: &Self) -> bool {
115        self.0.aeq_in(ctx, &other.0)
116    }
117
118    fn fv_in(&self, vars: &mut Vec<String>) {
119        self.0.fv_in(vars)
120    }
121}
122
123impl<T: Subst<V>, V> Subst<V> for Embed<T> {
124    fn is_var(&self) -> Option<SubstName<V>> {
125        None
126    }
127
128    fn subst(&self, var: &Name<V>, value: &V) -> Self {
129        Embed(self.0.subst(var, value))
130    }
131}
132
133/// System F terms
134#[derive(Clone, Debug, Alpha)]
135#[allow(dead_code)]
136enum Tm {
137    /// Term variables
138    TmVar(TmName),
139    /// Term abstraction (lambda)
140    Lam(Bind<(TmName, Embed<Ty>), Box<Tm>>),
141    /// Type abstraction (big lambda)
142    TLam(Bind<Vec<TyName>, Box<Tm>>),
143    /// Term application
144    App(Box<Tm>, Box<Tm>),
145    /// Type application
146    TApp(Box<Tm>, Vec<Ty>),
147}
148
149// Only need to specify when it's a variable for Subst<Tm>
150impl Subst<Tm> for Tm {
151    fn is_var(&self) -> Option<SubstName<Tm>> {
152        match self {
153            Tm::TmVar(v) => Some(SubstName::Name(v.clone())),
154            _ => None,
155        }
156    }
157
158    fn subst(&self, var: &Name<Tm>, value: &Tm) -> Self {
159        match self {
160            Tm::TmVar(v) if v == var => value.clone(),
161            Tm::TmVar(v) => Tm::TmVar(v.clone()),
162            Tm::Lam(b) => {
163                let (x, ann) = b.pattern();
164                if x == var {
165                    // Variable is bound, no substitution
166                    self.clone()
167                } else {
168                    // Substitute in body
169                    Tm::Lam(Bind::new(
170                        (x.clone(), ann.clone()),
171                        Box::new((**b.body()).subst(var, value)),
172                    ))
173                }
174            }
175            Tm::TLam(b) => {
176                // Type variables can't capture term variables, so substitute in body
177                Tm::TLam(Bind::new(
178                    b.pattern().clone(),
179                    Box::new((**b.body()).subst(var, value)),
180                ))
181            }
182            Tm::App(e1, e2) => Tm::App(
183                Box::new((**e1).subst(var, value)),
184                Box::new((**e2).subst(var, value)),
185            ),
186            Tm::TApp(t, tys) => Tm::TApp(Box::new((**t).subst(var, value)), tys.clone()),
187        }
188    }
189}
190
191// Subst Ty Tm - substituting types in terms
192impl Subst<Ty> for Tm {
193    fn is_var(&self) -> Option<SubstName<Ty>> {
194        None // Terms never contain type variables at the term level
195    }
196
197    fn subst(&self, var: &Name<Ty>, value: &Ty) -> Self {
198        match self {
199            Tm::TmVar(x) => Tm::TmVar(x.clone()),
200            Tm::Lam(b) => {
201                let (x, Embed(ty)) = b.pattern();
202                Tm::Lam(Bind::new(
203                    (x.clone(), Embed(ty.subst(var, value))),
204                    Box::new((**b.body()).subst(var, value)),
205                ))
206            }
207            Tm::TLam(b) => {
208                let vars = b.pattern();
209                if vars.iter().any(|v| v == var) {
210                    // Type variable is bound, no substitution
211                    self.clone()
212                } else {
213                    Tm::TLam(Bind::new(
214                        vars.clone(),
215                        Box::new((**b.body()).subst(var, value)),
216                    ))
217                }
218            }
219            Tm::App(e1, e2) => Tm::App(
220                Box::new((**e1).subst(var, value)),
221                Box::new((**e2).subst(var, value)),
222            ),
223            Tm::TApp(t, tys) => Tm::TApp(
224                Box::new((**t).subst(var, value)),
225                tys.iter().map(|ty| ty.subst(var, value)).collect(),
226            ),
227        }
228    }

Trait Implementations§

Source§

impl<T: Alpha, U: Alpha> Alpha for Bind<(Name<T>, U), Box<T>>

Source§

fn aeq(&self, other: &Self) -> bool

Check if two terms are alpha-equivalent
Source§

fn aeq_in(&self, ctx: &mut AlphaCtx, other: &Self) -> bool

Check alpha equivalence with a renaming context
Source§

fn fv_in(&self, vars: &mut Vec<String>)

Collect free variables into a vector
Source§

fn fv(&self) -> Vec<String>

Collect free variables
Source§

impl<T: Alpha> Alpha for Bind<Name<T>, Box<T>>

Source§

fn aeq(&self, other: &Self) -> bool

Check if two terms are alpha-equivalent
Source§

fn aeq_in(&self, ctx: &mut AlphaCtx, other: &Self) -> bool

Check alpha equivalence with a renaming context
Source§

fn fv_in(&self, vars: &mut Vec<String>)

Collect free variables into a vector
Source§

fn fv(&self) -> Vec<String>

Collect free variables
Source§

impl<T: Alpha, U: Alpha> Alpha for Bind<Vec<Name<T>>, Box<U>>

Source§

fn aeq(&self, other: &Self) -> bool

Check if two terms are alpha-equivalent
Source§

fn aeq_in(&self, ctx: &mut AlphaCtx, other: &Self) -> bool

Check alpha equivalence with a renaming context
Source§

fn fv_in(&self, vars: &mut Vec<String>)

Collect free variables into a vector
Source§

fn fv(&self) -> Vec<String>

Collect free variables
Source§

impl<P: Clone, T: Clone> Clone for Bind<P, T>

Source§

fn clone(&self) -> Bind<P, 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<P: Debug, T: Debug> Debug for Bind<P, T>

Source§

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

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

impl<P: Display, T: Display> Display for Bind<P, T>

Source§

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

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

impl<P: PartialEq, T: PartialEq> PartialEq for Bind<P, T>

Source§

fn eq(&self, other: &Bind<P, 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: Subst<V> + Clone, U: Subst<V> + Clone, V: Clone> Subst<V> for Bind<(Name<V>, U), Box<T>>

Source§

fn is_var(&self) -> Option<SubstName<V>>

Check if this term is a variable and return its name
Source§

fn subst(&self, var: &Name<V>, value: &V) -> Self

Perform substitution of value for var in self
Source§

fn subst_all(&self, subst_map: &HashMap<Name<V>, V>) -> Self
where V: Clone, Self: Clone,

Perform substitution with a mapping
Source§

impl<T: Subst<V> + Clone, V: Clone> Subst<V> for Bind<Name<V>, Box<T>>

Source§

fn is_var(&self) -> Option<SubstName<V>>

Check if this term is a variable and return its name
Source§

fn subst(&self, var: &Name<V>, value: &V) -> Self

Perform substitution of value for var in self
Source§

fn subst_all(&self, subst_map: &HashMap<Name<V>, V>) -> Self
where V: Clone, Self: Clone,

Perform substitution with a mapping
Source§

impl<T: Subst<V> + Clone, V: Clone> Subst<V> for Bind<Vec<Name<V>>, Box<T>>

Source§

fn is_var(&self) -> Option<SubstName<V>>

Check if this term is a variable and return its name
Source§

fn subst(&self, var: &Name<V>, value: &V) -> Self

Perform substitution of value for var in self
Source§

fn subst_all(&self, subst_map: &HashMap<Name<V>, V>) -> Self
where V: Clone, Self: Clone,

Perform substitution with a mapping
Source§

impl<P, T> StructuralPartialEq for Bind<P, T>

Auto Trait Implementations§

§

impl<P, T> Freeze for Bind<P, T>
where P: Freeze, T: Freeze,

§

impl<P, T> RefUnwindSafe for Bind<P, T>

§

impl<P, T> Send for Bind<P, T>
where P: Send, T: Send,

§

impl<P, T> Sync for Bind<P, T>
where P: Sync, T: Sync,

§

impl<P, T> Unpin for Bind<P, T>
where P: Unpin, T: Unpin,

§

impl<P, T> UnwindSafe for Bind<P, T>
where P: UnwindSafe, 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.