public override string ToString()
        {
            var builder = new PrettyBuilder();

            Pretty(builder);
            return(builder.ToString());
        }
        // List<LiftedFunctionExpression> Functions;
        // Expression MainExpression;

        public override string ToString()
        {
            var builder = new PrettyBuilder();

            Functions.ForEach(
                function => {
                function.Pretty(builder);
                builder.NewLine();
            });
            MainExpression.Pretty(builder);
            return(builder.ToString());
        }
        // public string Name ;
        // public Expression Argument;

        override public void Pretty(PrettyBuilder builder, int outerPrecedence, bool opposite)
        {
            if (outerPrecedence >= 4)
            {
                builder.Append("(");
            }

            builder.Append($"{Name} ");
            Argument.Pretty(builder, 4, false);

            if (outerPrecedence >= 4)
            {
                builder.Append(")");
            }
        }
        // public string Name;
        // public Expression Expression;
        // public Expression Recipient;

        override public void Pretty(PrettyBuilder builder, int outerPrecedence, bool opposite)
        {
            if (outerPrecedence > 1)
            {
                builder.Append("(");
            }

            builder.Append($"let {Name} = ");
            Expression.Pretty(builder, 1, false);
            builder.Append(" in ");
            Recipient.Pretty(builder, 1, false);

            if (outerPrecedence > 1)
            {
                builder.Append(")");
            }
        }
        // public string Name;
        // public string ArgumentName;
        // public Type ArgumentType
        // public Type ReturnType
        // public Expression Body;
        // public Expression Recipient;

        override public void Pretty(PrettyBuilder builder, int outerPrecedence, bool opposite)
        {
            if (outerPrecedence > 1)
            {
                builder.Append("(");
            }

            builder.Append($"let {Name} {ArgumentName} : {ArgumentType} -> {ReturnType} = ");
            Body.Pretty(builder, 1, false);
            builder.Append(" in ");
            Recipient.Pretty(builder, 1, false);

            if (outerPrecedence > 1)
            {
                builder.Append(")");
            }
        }
        override public void Pretty(PrettyBuilder builder, int outerPrecedence, bool opposite)
        {
            var precedence    = Precedences[Operator];
            var associativity = Associativities[Operator];

            if (outerPrecedence > precedence || opposite && outerPrecedence == precedence)
            {
                builder.Append("(");
            }

            Expression1.Pretty(builder, precedence, associativity == Associativity.Right);
            builder.Append(Strings[Operator]);
            Expression2.Pretty(builder, precedence, associativity == Associativity.Left);

            if (outerPrecedence > precedence || opposite && outerPrecedence == precedence)
            {
                builder.Append(")");
            }
        }
        // public Expression Expression1;
        // public Expression Expression2;

        override public void Pretty(PrettyBuilder builder, int outerPrecedence, bool opposite)
        {
            if (outerPrecedence > 0)
            {
                builder.Append("(");
                builder.Indent();
                builder.NewLine();
            }
            Expression1.Pretty(builder, 0, false);
            builder.Append(", ");
            builder.NewLine();
            Expression2.Pretty(builder, 0, false);
            if (outerPrecedence > 0)
            {
                builder.Unindent();
                builder.NewLine();
                builder.Append(")");
                builder.NewLine();
            }
        }
        // public string Name;
        // public List<string> ArgumentNames;
        // public List<Type> ArgumentTypes;
        // public Type ReturnType;
        // public Expression Body;


        public override void Pretty(PrettyBuilder builder, int outerPrecedence, bool opposite)
        {
            if (outerPrecedence > 1)
            {
                builder.Append("(");
            }

            builder.Append($"let {Name} ");
            for (var i = 0; i < ArgumentNames.Count; i++)
            {
                builder.Append($"{ArgumentNames[i]} ");
            }
            builder.Append($"= ");

            Body.Pretty(builder, 1, false);

            if (outerPrecedence > 1)
            {
                builder.Append(")");
            }
        }
 public abstract void Pretty(PrettyBuilder builder, int outerPrecedence, bool opposite);
 public void Pretty(PrettyBuilder builder)
 {
     Pretty(builder, 0, false);
 }
 // public string Value;
 override public void Pretty(PrettyBuilder builder, int outerPrecedence, bool opposite)
 {
     builder.Append(Value.ToString());
 }
        // public string Name;

        override public void Pretty(PrettyBuilder builder, int outerPrecedence, bool opposite)
        {
            builder.Append(Name);
        }