using System; using Ast; public class Visitor { public Func Int { get; set; } public Func String { get; set; } } namespace Ast { public interface Expr { T Match_(Visitor c); } public abstract class Const : Expr { public readonly T value; public Const(T value) { this.value = value; } public abstract U Match_(Visitor c); } public class Int : Const { public Int(int x) : base(x) {} public override T Match_(Visitor c) => c.Int(value); } public class String : Const { public String(string x) : base(x) {} public override T Match_(Visitor c) => c.String(value); } } public static class AstExtensionMethods { public static T Match( this Ast.Expr e, Func Int, Func String ) { return e.Match_(new Visitor { Int = Int, String = String }); } }