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>
impl<P, T> Bind<P, T>
Sourcepub fn new(pattern: P, body: T) -> Self
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 }
Sourcepub fn unbind(self) -> (P, T)
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
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}
Sourcepub fn pattern(&self) -> &P
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 }
Sourcepub fn body(&self) -> &T
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>>
impl<T: Alpha, U: Alpha> Alpha for Bind<(Name<T>, U), Box<T>>
Source§impl<T: Alpha> Alpha for Bind<Name<T>, Box<T>>
impl<T: Alpha> Alpha for Bind<Name<T>, Box<T>>
Source§impl<T: Alpha, U: Alpha> Alpha for Bind<Vec<Name<T>>, Box<U>>
impl<T: Alpha, U: Alpha> Alpha for Bind<Vec<Name<T>>, Box<U>>
Source§impl<T: Subst<V> + Clone, U: Subst<V> + Clone, V: Clone> Subst<V> for Bind<(Name<V>, U), Box<T>>
impl<T: Subst<V> + Clone, U: Subst<V> + Clone, V: Clone> Subst<V> for Bind<(Name<V>, U), Box<T>>
Source§impl<T: Subst<V> + Clone, V: Clone> Subst<V> for Bind<Name<V>, Box<T>>
impl<T: Subst<V> + Clone, V: Clone> Subst<V> for Bind<Name<V>, Box<T>>
Source§impl<T: Subst<V> + Clone, V: Clone> Subst<V> for Bind<Vec<Name<V>>, Box<T>>
impl<T: Subst<V> + Clone, V: Clone> Subst<V> for Bind<Vec<Name<V>>, Box<T>>
impl<P, T> StructuralPartialEq for Bind<P, T>
Auto Trait Implementations§
impl<P, T> Freeze for Bind<P, T>
impl<P, T> RefUnwindSafe for Bind<P, T>where
P: RefUnwindSafe,
T: RefUnwindSafe,
impl<P, T> Send for Bind<P, T>
impl<P, T> Sync for Bind<P, T>
impl<P, T> Unpin for Bind<P, T>
impl<P, T> UnwindSafe for Bind<P, T>where
P: UnwindSafe,
T: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more