All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fj.data.hlist.HPre Maven / Gradle / Ivy

Go to download

Functional Java is an open source library that supports closures for the Java programming language

There is a newer version: 5.0
Show newest version
package fj.data.hlist;

import fj.Show;

/**
 * A basic prelude of values lifted into the type system.
 */
@SuppressWarnings({"ALL"})
public final class HPre {
  private HPre() {
    throw new UnsupportedOperationException();
  }

  /**
   * A type-level Boolean
   */
  public static class HBool {
    private HBool() {
    }
  }

  /**
   * Boolean true
   */
  public static class HTrue extends HBool {
    private HTrue() {
    }
  }

  /**
   * Boolean false
   */
  public static class HFalse extends HBool {
    private HFalse() {
    }
  }

  private static final HTrue hTrue = new HTrue();
  private static final HFalse hFalse = new HFalse();

  /**
   * Returns a boolean value whose type represents truth.
   *
   * @return a boolean value whose type represents truth.
   */
  public static HTrue hTrue() {
    return hTrue;
  }

  /**
   * Returns a boolean value whose type represents falsehood.
   *
   * @return a boolean value whose type represents falsehood.
   */
  public static HFalse hFalse() {
    return hFalse;
  }

  /**
   * Type-level boolean conjunction. A value of this type represents evidence that AB -> C
   *
   * @param  A boolean
   * @param  A boolean
   * @param  The logical implication of A and B
   */
  public static final class HAnd {
    private final C v;

    private HAnd(final C v) {
      this.v = v;
    }

    public C v() {
      return v;
    }

    public static HAnd hAnd(final HFalse a, final HFalse b) {
      return new HAnd(hFalse());
    }

    public static HAnd hAnd(final HTrue a, final HFalse b) {
      return new HAnd(hFalse());
    }

    public static HAnd hAnd(final HFalse a, final HTrue b) {
      return new HAnd(hFalse());
    }

    public static HAnd hAnd(final HTrue a, final HTrue b) {
      return new HAnd(hTrue());
    }
  }

  /**
   * Type-level boolean disjunction. A value of this type represents evidence that A+B -> C
   *
   * @param  A boolean
   * @param  A boolean
   * @param  The logical implication of A or B
   */
  public static final class HOr {
    private final C v;

    private HOr(final C v) {
      this.v = v;
    }

    public C v() {
      return v;
    }

    public static HOr hOr(final HFalse a, final HFalse b) {
      return new HOr(hFalse());
    }

    public static HOr hOr(final HTrue a, final HFalse b) {
      return new HOr(hTrue());
    }

    public static HOr hOr(final HFalse a, final HTrue b) {
      return new HOr(hTrue());
    }

    public static HOr hOr(final HTrue a, final HTrue b) {
      return new HOr(hTrue());
    }
  }

  /**
   * A type-level conditional. The type of the last parameter is implied by the first three.
   *
   * @param  A boolean
   * @param  The type of Z if T is true.
   * @param  The type of Z if T is false.
   * @param  A type that is either X or Z, depending on T.
   */
  public static final class HCond {
    private HCond(final Z z) {
      this.z = z;
    }

    private final Z z;

    public Z v() {
      return z;
    }

    public static  HCond hCond(final HFalse t, final X x, final Y y) {
      return new HCond(y);
    }

    public static  HCond hCond(final HTrue t, final X x, final Y y) {
      return new HCond(x);
    }
  }

  /**
   * Type-level natural numbers.
   */
  public abstract static class HNat> {
    public abstract Show show();

    public abstract Integer toInteger();

    public static HZero hZero() {
      return new HZero();
    }

    public static > HSucc hSucc(final N n) {
      return new HSucc(n);
    }

    public static > N hPred(final HSucc n) {
      return n.pred;
    }
  }

  /**
   * Type-level zero
   */
  public static final class HZero extends HNat {
    private HZero() {
    }

    public Show show() {
      return Show.showS(hZero -> "HZero");
    }

    public Integer toInteger() {
      return 0;
    }
  }

  /**
   * A natural number N + 1
   *
   * @param  The predecessor of this number.
   */
  public static final class HSucc> extends HNat> {
    private HSucc(final N n) {
      pred = n;
    }

    private final N pred;

    public Show> show() {
      return Show.showS(s -> "HSucc (" + s.show().showS(s) + ')');
    }

    public Integer toInteger() {
      return 1 + pred.toInteger();
    }
  }

  /**
   * Type-level equality. Represents evidence for X and Y being equal, or counterevidence against.
   */
  public static final class HEq {
    private final B v;

    private HEq(final B v) {
      this.v = v;
    }

    public B v() {
      return v;
    }

    /**
     * Zero is equal to itself.
     *
     * @param a Zero
     * @param b Zero
     * @return Equality for Zero
     */
    public static HEq eq(final HZero a, final HZero b) {
      return new HEq(hTrue());
    }

    /**
     * Zero is not equal to anything other than zero.
     */
    public static > HEq, HFalse> eq(final HZero a, final HSucc b) {
      return new HEq, HFalse>(hFalse());
    }

    /**
     * Zero is not equal to anything other than zero.
     */
    public static > HEq, HZero, HFalse> eq(final HSucc a, final HZero b) {
      return new HEq, HZero, HFalse>(hFalse());
    }

    /**
     * A number is equal to another if their predecessors are equal.
     */
    public static , NN extends HNat, B extends HBool, E extends HEq>
    HEq, HSucc, B> eq(final HSucc a, final HSucc b, final E e) {
      return new HEq, HSucc, B>(e.v());
    }

  }

  /**
   * Type-level integer arithmetic
   */
  public static final class HAdd, B extends HNat, C extends HNat> {
    private final C sum;

    private HAdd(final C sum) {
      this.sum = sum;
    }

    public C sum() {
      return this.sum;
    }

    /**
     * The sum of zero and any other number is that number.
     */
    public static > HAdd, HSucc> add(final HZero a, final HSucc b) {
      return new HAdd, HSucc>(b);
    }

    /**
     * The sum of zero and any other number is that number.
     */
    public static > HAdd, HZero, HSucc> add(final HSucc a, final HZero b) {
      return new HAdd, HZero, HSucc>(a);
    }

    /**
     * The sum of numbers a and b is one greater than the sum of b and the predecessor of a.
     */
    public static , M extends HNat, R extends HNat, H extends HAdd, R>>
    HAdd, HSucc, HSucc> add(final HSucc a, final HSucc b, final H h) {
      return new HAdd, HSucc, HSucc>(HNat.hSucc(h.sum()));
    }
  }

}