private LambdaExpression Subst(LambdaExpression expr, Variable variable, LambdaExpression subst, HashSet <Variable> variables) { if (expr is Variable) { if (expr.Equals(variable)) { return(Rename(variables, subst)); } return(null); } if (expr is Abstraction) { var abstraction = expr as Abstraction; if (variables.Contains(abstraction.Variable)) { throw new Exception("Assert"); } variables.Add(abstraction.Variable); var r0 = Subst(abstraction.Expression, variable, subst, variables); variables.Remove(abstraction.Variable); if (r0 == null) { return(abstraction); } return(new Abstraction(abstraction.Variable, r0)); } if (expr is Application) { var application = expr as Application; var s0 = Subst(application.Left, variable, subst, variables); var s1 = Subst(application.Right, variable, subst, variables); if (s0 == null && s1 == null) { return(null); } return(new Application(s0 ?? application.Left, s1 ?? application.Right)); } throw new NotImplementedException(expr.GetType().Name + " doesn't support subst"); }