Skip to content

Instantly share code, notes, and snippets.

@akarpov89
Created March 16, 2020 09:35
Show Gist options
  • Save akarpov89/3cc016d5afd9491444f247d3ba56b4ed to your computer and use it in GitHub Desktop.
Save akarpov89/3cc016d5afd9491444f247d3ba56b4ed to your computer and use it in GitHub Desktop.
Summer Internship 2020 Task
using System;
using System.Text;
namespace InternshipTask
{
public interface IExpression
{
T Accept<T>(IVisitor<T> visitor);
}
public interface IVisitor<out T>
{
T Visit(Application expression);
T Visit(Abstraction expression);
T Visit(Variable expression);
}
public sealed class Application : IExpression
{
public IExpression Function { get; }
public IExpression Argument { get; }
public Application(IExpression function, IExpression argument)
{
Function = function;
Argument = argument;
}
public T Accept<T>(IVisitor<T> visitor)
{
return visitor.Visit(this);
}
public override string ToString()
{
return Presenter.ToString(this);
}
}
public sealed class Abstraction : IExpression
{
public Variable Variable { get; }
public IExpression Body { get; }
public Abstraction(Variable variable, IExpression body)
{
Variable = variable;
Body = body;
}
public T Accept<T>(IVisitor<T> visitor)
{
return visitor.Visit(this);
}
public override string ToString()
{
return Presenter.ToString(this);
}
}
public sealed class Variable : IExpression
{
public string Name { get; }
public Variable(string name)
{
Name = name;
}
public T Accept<T>(IVisitor<T> visitor)
{
return visitor.Visit(this);
}
public override string ToString()
{
return Presenter.ToString(this);
}
private bool Equals(Variable other)
{
return Name == other.Name;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Variable) obj);
}
public override int GetHashCode()
{
return Name.GetHashCode();
}
}
public sealed class Presenter : IVisitor<StringBuilder>
{
private readonly StringBuilder myBuilder;
private Presenter(StringBuilder builder)
{
myBuilder = builder;
}
public StringBuilder Visit(Application expression)
{
if (expression.Function is Abstraction abstraction)
{
myBuilder.Append("let ");
abstraction.Variable.Accept(this);
myBuilder.Append(" = ");
expression.Argument.Accept(this);
myBuilder.Append(" in ");
if (abstraction.Body is Application application && application.Function is Abstraction)
myBuilder.AppendLine();
return abstraction.Body.Accept(this);
}
// else
{
expression.Function.Accept(this);
myBuilder.Append("(");
expression.Argument.Accept(this);
return myBuilder.Append(")");
}
}
public StringBuilder Visit(Abstraction expression)
{
myBuilder.Append("\\");
expression.Variable.Accept(this);
myBuilder.Append(" => ");
return expression.Body.Accept(this);
}
public StringBuilder Visit(Variable expression)
{
return myBuilder.Append(expression.Name);
}
public static string ToString(IExpression expression)
{
return expression.Accept(new Presenter(new StringBuilder())).ToString();
}
}
public class Reducer : IVisitor<IExpression>
{
public IExpression Visit(Application expression)
{
throw new NotImplementedException("Implement me!");
}
public IExpression Visit(Abstraction expression)
{
throw new NotImplementedException("Implement me!");
}
public IExpression Visit(Variable expression)
{
throw new NotImplementedException("Implement me!");
}
}
public static class Program
{
public static void Main()
{
var expr = new Application(new Abstraction(new Variable("zero"), new Application(new Abstraction(new Variable("one"), new Application(new Abstraction(new Variable("two"), new Application(new Abstraction(new Variable("succ"), new Application(new Abstraction(new Variable("plus"), new Application(new Abstraction(new Variable("mult"), new Application(new Abstraction(new Variable("pred"), new Application(new Abstraction(new Variable("true"), new Application(new Abstraction(new Variable("false"), new Application(new Abstraction(new Variable("if"), new Application(new Abstraction(new Variable("izzero"), new Application(new Abstraction(new Variable("fix"), new Application(new Abstraction(new Variable("factorial"), new Application(new Variable("factorial"), new Application(new Application(new Variable("plus"), new Application(new Application(new Variable("mult"), new Variable("two")), new Variable("two"))), new Variable("two")))), new Application(new Variable("fix"), new Abstraction(new Variable("f"), new Abstraction(new Variable("n"), new Application(new Application(new Application(new Variable("if"), new Application(new Variable("izzero"), new Variable("n"))), new Variable("one")), new Application(new Application(new Variable("mult"), new Variable("n")), new Application(new Variable("f"), new Application(new Variable("pred"), new Variable("n")))))))))), new Abstraction(new Variable("g"), new Application(new Abstraction(new Variable("x"), new Application(new Variable("g"), new Application(new Variable("x"), new Variable("x")))), new Abstraction(new Variable("x"), new Application(new Variable("g"), new Application(new Variable("x"), new Variable("x")))))))), new Abstraction(new Variable("n"), new Application(new Application(new Variable("n"), new Abstraction(new Variable("x"), new Variable("false"))), new Variable("true"))))), new Abstraction(new Variable("p"), new Abstraction(new Variable("x"), new Abstraction(new Variable("y"), new Application(new Application(new Variable("p"), new Variable("x")), new Variable("y"))))))), new Abstraction(new Variable("x"), new Abstraction(new Variable("y"), new Variable("y"))))), new Abstraction(new Variable("x"), new Abstraction(new Variable("y"), new Variable("x"))))), new Abstraction(new Variable("n"), new Abstraction(new Variable("f"), new Abstraction(new Variable("x"), new Application(new Application(new Application(new Variable("n"), new Abstraction(new Variable("g"), new Abstraction(new Variable("h"), new Application(new Variable("h"), new Application(new Variable("g"), new Variable("f")))))), new Abstraction(new Variable("u"), new Variable("x"))), new Abstraction(new Variable("u"), new Variable("u")))))))), new Abstraction(new Variable("m"), new Abstraction(new Variable("n"), new Application(new Application(new Variable("m"), new Application(new Variable("plus"), new Variable("n"))), new Variable("zero")))))), new Abstraction(new Variable("m"), new Abstraction(new Variable("n"), new Abstraction(new Variable("f"), new Abstraction(new Variable("x"), new Application(new Application(new Variable("n"), new Variable("f")), new Application(new Application(new Variable("m"), new Variable("f")), new Variable("x"))))))))), new Abstraction(new Variable("n"), new Abstraction(new Variable("f"), new Abstraction(new Variable("x"), new Application(new Variable("f"), new Application(new Application(new Variable("n"), new Variable("f")), new Variable("x")))))))), new Abstraction(new Variable("f"), new Abstraction(new Variable("x"), new Application(new Variable("f"), new Application(new Variable("f"), new Variable("x"))))))), new Abstraction(new Variable("f"), new Abstraction(new Variable("x"), new Application(new Variable("f"), new Variable("x")))))), new Abstraction(new Variable("f"), new Abstraction(new Variable("x"), new Variable("x"))));
Console.WriteLine(Presenter.ToString(expr));
Console.ReadLine();
Console.WriteLine(Presenter.ToString(expr.Accept(new Reducer())));
Console.ReadLine();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment