Relational.java
package church.lang.operators;

import static church.lang.operators.Relational.Ordering.*;

@SuppressWarnings("unchecked")
public class Relational {
    public static enum Ordering {
        LT, EQ, GT
    }

    public static interface $Compare<T> {
        public Ordering compare(T a, T b);
    }

    public static interface $$equal<T> {
        public boolean $equal(T a, T b);
    }

    public static <T> $$equal<T> $equal($Compare<T> $L0) {
        return (a, b) -> $L0.compare(a, b) == EQ;
    }

    public static interface $$neq<T> {
        public boolean $neq(T a, T b);
    }

    public static <T> $$neq<T> $neq($$equal<T> $L0) {
        return (a, b) -> !$L0.$equal(a, b);
    }

    public static interface $$lt<T> {
        public boolean $lt(T a, T b);
    }

    public static <T> $$lt<T> $lt($Compare<T> $L0) {
        return (a, b) -> $L0.compare(a, b) == LT;
    }

    public static interface $$gt<T> {
        public boolean $gt(T a, T b);
    }

    public static <T> $$gt<T> $gt($Compare<T> $L0) {
        return (a, b) -> $L0.compare(a, b) == GT;
    }

    public static interface $$lte<T> {
        public boolean $lte(T a, T b);
    }

    public static <T> $$lte<T> $lte($Compare<T> $L0) {
        return (a, b) -> $L0.compare(a, b) != GT;
    }

    public static interface $$gte<T> {
        public boolean $gte(T a, T b);
    }

    public static <T> $$gte<T> $gte($Compare<T> $L0) {
        return (a, b) -> $L0.compare(a, b) != LT;
    }

    public static interface $Min<T> {
        public T min(T a, T b);
    }

    public static <T> $Min<T> min($$lte<T> $L0) {
        return (a, b) -> $L0.$lte(a, b) ? a : b;
    }

    public static interface $Max<T> {
        public T max(T a, T b);
    }

    public static <T> $Max<T> max($$gte<T> $L0) {
        return (a, b) -> $L0.$gte(a, b) ? a : b;
    }

}