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

fj.Show 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;

import fj.data.*;
import fj.data.fingertrees.FingerTree;
import fj.data.fingertrees.Node;
import fj.data.hlist.HList;
import fj.data.vector.V2;
import fj.data.vector.V3;
import fj.data.vector.V4;
import fj.data.vector.V5;
import fj.data.vector.V6;
import fj.data.vector.V7;
import fj.data.vector.V8;

import java.math.BigDecimal;
import java.math.BigInteger;

import static fj.Function.compose;
import static fj.P.p;
import static fj.Unit.unit;
import static fj.data.Stream.cons;
import static fj.data.Stream.fromString;
import static fj.data.Stream.join;
import static fj.data.Stream.single;

/**
 * Renders an object for display.
 *
 * @version %build.number%
 */
public final class Show {
  private final F> f;

  private Show(final F> f) {
    this.f = f;
  }

  /**
   * Maps the given function across this show as a contra-variant functor.
   *
   * @param f The function to map.
   * @return A new show.
   */
  public  Show contramap(final F f) {
    return show(compose(this.f, f));
  }

  /**
   * Returns the display rendering of the given argument.
   *
   * @param a The argument to display.
   * @return The display rendering of the given argument.
   */
  public Stream show(final A a) {
    return f.f(a);
  }

  /**
   * Returns the display rendering of the given argument.
   *
   * @param a The argument to display.
   * @return The display rendering of the given argument.
   */
  public List showl(final A a) {
    return show(a).toList();
  }

  /**
   * Returns the display rendering of the given argument as a String.
   *
   * @param a The argument to display.
   * @return The display rendering of the given argument as a String.
   */
  public String showS(final A a) {
    return Stream.asString(show(a));
  }

  /**
   * Returns the transformation equivalent to this show.
   *
   * @return the transformation equivalent to this show.
   */
  public F showS_() {
    return this::showS;
  }

  /**
   * Returns the transformation equivalent to this show.
   *
   * @return the transformation equivalent to this show.
   */
  public F> show_() {
    return f;
  }

  /**
   * Prints the given argument to the standard output stream with a new line.
   *
   * @param a The argument to print.
   * @return The unit value.
   */
  public Unit println(final A a) {
    print(a);
    System.out.println();
    return unit();
  }

  /**
   * Prints the given argument to the standard output stream.
   *
   * @param a The argument to print.
   * @return The unit value.
   */
  public Unit print(final A a) {
    final char[] buffer = new char[8192];
    int c = 0;
    for (Stream cs = show(a); cs.isNotEmpty(); cs = cs.tail()._1()) {
      buffer[c] = cs.head();
      c++;
      if (c == 8192) {
        System.out.print(buffer);
        c = 0;
      }
    }
    System.out.print(Array.copyOfRange(buffer, 0, c));
    return unit();
  }

  /**
   * Prints the given argument to the standard error stream with a new line.
   *
   * @param a The argument to print.
   */
  public void printlnE(final A a) {
    System.err.println(showS(a));
  }

  /**
   * Returns a show instance using the given function.
   *
   * @param f The function to use for the returned show instance.
   * @return A show instance.
   */
  public static  Show show(final F> f) {
    return new Show<>(f);
  }

  /**
   * Returns a show instance using the given function.
   *
   * @param f The function to use for the returned show instance.
   * @return A show instance.
   */
  public static  Show showS(final F f) {
    return show(a -> fromString(f.f(a)));
  }

  /**
   * Returns a show instance that uses {@link Object#toString()} to perform the display rendering.
   *
   * @return A show instance that uses {@link Object#toString()} to perform the display rendering.
   */
  public static  Show anyShow() {
    return show(a -> fromString((a == null) ? "null" : a.toString()));
  }

  /**
   * A show instance for the boolean type.
   */
  public static final Show booleanShow = anyShow();

  /**
   * A show instance for the byte type.
   */
  public static final Show byteShow = anyShow();

  /**
   * A show instance for the char type.
   */
  public static final Show charShow = anyShow();

  /**
   * A show instance for the double type.
   */
  public static final Show doubleShow = anyShow();

  /**
   * A show instance for the float type.
   */
  public static final Show floatShow = anyShow();

  /**
   * A show instance for the int type.
   */
  public static final Show intShow = anyShow();

  /**
   * A show instance for the BigInteger type.
   */
  public static final Show bigintShow = anyShow();

  /**
   * A show instance for the BigDecimal type.
   */
  public static final Show bigdecimalShow = anyShow();

  /**
   * A show instance for the long type.
   */
  public static final Show longShow = anyShow();

  /**
   * A show instance for the short type.
   */
  public static final Show shortShow = anyShow();

  /**
   * A show instance for the {@link String} type.
   */
  public static final Show stringShow = anyShow();

  /**
   * A show instance for the {@link StringBuffer} type.
   */
  public static final Show stringBufferShow = anyShow();

  /**
   * A show instance for the {@link StringBuilder} type.
   */
  public static final Show stringBuilderShow = anyShow();

  /**
   * A show instance for the {@link Option} type.
   *
   * @param sa Show for the element of the option.
   * @return A show instance for the {@link Option} type.
   */
  public static  Show> optionShow(final Show sa) {
    return show(o -> o.isNone() ?
           fromString("None") :
           fromString("Some(").append(sa.f.f(o.some())).append(single(')')));
  }

  /**
   * A show instance for the {@link Either} type.
   *
   * @param sa Show for the left side of the {@link Either}.
   * @param sb Show for the right side of the {@link Either}.
   * @return A show instance for the {@link Either} type.
   */
  public static  Show> eitherShow(final Show sa, final Show sb) {
    return show(e -> e.isLeft() ?
           fromString("Left(").append(sa.f.f(e.left().value())).append(single(')')) :
           fromString("Right(").append(sb.f.f(e.right().value())).append(single(')')));
  }

  /**
   * A show instance for the {@link Validation} type.
   *
   * @param sa Show for the fail side of the {@link Validation}.
   * @param sb Show for the success side of the {@link Validation}.
   * @return A show instance for the {@link Validation} type.
   */
  public static  Show> validationShow(final Show sa, final Show sb) {
    return show(v -> v.isFail() ?
           fromString("Fail(").append(sa.f.f(v.fail())).append(single(')')) :
           fromString("Success(").append(sb.f.f(v.success())).append(single(')')));
  }

  /**
   * A show instance for the {@link Stream} type.
   *
   * @param sa Show for the elements of the Stream.
   * @return A show instance for the {@link Stream} type.
   */
  public static  Show> listShow(final Show sa) {
    return show(as -> streamShow(sa, "List(", ",", ")").show(as.toStream()));
  }

  /**
   * A show instance for the {@link NonEmptyList} type.
   *
   * @param sa Show for the elements of the non-empty Stream.
   * @return A show instance for the {@link NonEmptyList} type.
   */
  public static  Show> nonEmptyListShow(final Show sa) {
    return listShow(sa).contramap(NonEmptyList.toList_());
  }

  /**
   * A show instance for the {@link Tree} type.
   *
   * @param sa Show for the elements of the tree.
   * @return A show instance for the {@link Tree} type.
   */
  public static  Show> treeShow(final Show sa) {
    return show(a -> {
      Stream result = sa.f.f(a.root());
      if (!a.subForest()._1().isEmpty()) {
        result = result.append(fromString(",")).append(streamShow(treeShow(sa), "", ",", "").f.f(a.subForest()._1()));
      }
      return fromString("Tree(").append(p(result)).append(fromString(")"));
    });
  }

  public static  Show> digitShow(final Show sv, final Show sa) {
    return show(d -> {
      String s = d.match(
              o -> "One(" + o.measure() + " -> " + o.value() + ")",
              two -> "Two(" + two.measure() + " -> " + v2Show(sa).showS(two.values()) + ")",
              three -> "Three(" + three.measure() + " -> " + v3Show(sa).showS(three.values()) + ")",
              four -> "Four(" + four.measure() + " -> " + v4Show(sa).showS(four.values()) + ")"
      );
      return Stream.fromString(s);
    });
  }

  public static  Show> nodeShow(final Show sv, final Show sa) {
    return show(n -> {
      final String s = n.match(
          n2 -> "Node2(" + n2.measure() + " -> " + v2Show(sa).showS(n2.toVector()) + ")",
          n3 -> "Node3(" + n3.measure() + " -> " + v3Show(sa).showS(n3.toVector()) + ")");
      return Stream.fromString(s);
    });
  }

  public static  Show> fingerTreeShow(final Show sv, final Show sa) {

    return show(ft -> {
      String sep = ", ";
      String str = ft.match(e -> "Empty()",
              s -> "Single(" + sv.showS(ft.measure()) + " -> " + sa.showS(s.value()) + ")",
              d -> "Deep(" + d.measure() + " -> " +
                      digitShow(sv, sa).showS(d.prefix()) + sep +
                      fingerTreeShow(sv, nodeShow(sv, sa)).showS(d.middle()) + sep +
                      digitShow(sv, sa).showS(d.suffix()) +
                      ")"
      );
      return Stream.fromString(str);
    });
  }


  public static  Show> seqShow(final Show sa) {
    return show(s -> streamShow(sa, "Seq(", ",", ")").show(s.toStream()));
  }

  /**
   * A show instance for the {@link Set} type.
   *
   * @param sa Show for the elements of the set.
   * @return A show instance for the {@link Set} type.
   */
  public static  Show> setShow(final Show sa) {
    return show(s -> streamShow(sa, "Set(", ",", ")").show(s.toStream()));
  }

  /**
   * A show instance for the {@link TreeMap} type.
   *
   * @param sk Show for the keys of the TreeMap.
   * @param sv Show for the values of the TreeMap.
   * @return A show instance for the {@link TreeMap} type.
   */
  public static  Show> treeMapShow(final Show sk, final Show sv) {
    return show(tm -> {
      Stream> stream = Stream.iteratorStream(tm.iterator());
      return streamShow(p2MapShow(sk, sv), "TreeMap(", ",", ")").show(stream);
    });
  }

  /**
   * A show instance for the {@link P2 tuple-2} type in the style of a mapping from A to B.
   *
   * @param sa Show for the first element of the tuple.
   * @param sb Show for the second element of the tuple.
   * @return A show instance for the {@link P2 tuple-2} type.
   */
  public static  Show> p2MapShow(final Show sa, final Show sb) {
    return p2Show(sa, sb, "(", ": ", ")");
  }

  /**
   * A show instance for the {@link P2 tuple-2} type.
   *
   * @param sa Show for the first element of the tuple.
   * @param sb Show for the second element of the tuple.
   * @param start Prefix string for the show.
   * @param sep Separator string between elements of the tuple.
   * @param end Suffix string for the show.
   * @return A show instance for the {@link P2 tuple-2} type.
   */
  public static  Show> p2Show(final Show sa, final Show sb, String start, String sep, String end) {
    return show(p -> fromString(start).append(p(sa.show(p._1()))).append(fromString(sep)).append(sb.show(p._2())).append(fromString(end)));
  }

  /**
   * A show instance for the {@link Stream} type.
   *
   * @param sa Show for the elements of the stream.
   * @return A show instance for the {@link Stream} type.
   */
  public static  Show> streamShow(final Show sa) {
    return streamShow(sa, "Stream(", ",", ")");
  }

  /**
   * A show instance for the {@link Stream} type.
   *
   * @param sa Show for the first element of the tuple.
   * @param start Prefix string for the show.
   * @param sep Separator string between elements of the stream.
   * @param end Suffix string for the show.
   * @return A show instance for the {@link Stream} type.
   */
  public static  Show> streamShow(final Show sa, String start, String sep, String end) {
    return show(streamShow_(sa, start, sep, end));
  }

  /**
   * Returns the transformation equivalent for the stream show.
   */
  public static  F, Stream> streamShow_(final Show sa, String start, String sep, String end) {
    return as -> join(as.map(sa.show_()).intersperse(fromString(sep)).cons(fromString(start)).snoc(p(fromString(end))));
  }

  /**
   * A show instance for the {@link Array} type.
   *
   * @param sa Show for the elements of the array.
   * @return A show instance for the {@link Array} type.
   */
  public static  Show> arrayShow(final Show sa) {
    return show(as -> {
      Stream b = fromString("Array(");

      for (int i = 0; i < as.length(); i++) {
        b = b.append(sa.f.f(as.get(i)));

        if (i != as.length() - 1)
          b = b.append(fromString(","));
      }

      return b.append(fromString(")"));
    });
  }

  /**
   * A show instance for the {@link Class} type.
   *
   * @return A show instance for the {@link Class} type.
   */
  public static  Show> classShow() {
    return show(c -> anyShow().show(c.clas()));
  }

  /**
   * A show instance for the {@link P1 tuple-1} type.
   *
   * @param sa Show for the first element of the tuple.
   * @return A show instance for the {@link P1 tuple-1} type.
   */
  public static  Show> p1Show(final Show sa) {
    return p1ShowLazy(sa);
  }

  public static  Show> p1ShowLazy(final Show sa) {
    return show(p -> fromString("(?)"));
  }

  public static  Show> p1ShowEager(final Show sa) {
    return show(p -> cons('(', p(sa.show(p._1()))).snoc(')'));
  }

  /**
   * A show instance for the {@link P2 tuple-2} type.
   *
   * @param sa Show for the first element of the tuple.
   * @param sb Show for the second element of the tuple.
   * @return A show instance for the {@link P2 tuple-2} type.
   */
  public static  Show> p2Show(final Show sa, final Show sb) {
      return p2Show(sa, sb, "(", ",", ")");
  }

  /**
   * A show instance for the {@link P3 tuple-3} type.
   *
   * @param sa Show for the first element of the tuple.
   * @param sb Show for the second element of the tuple.
   * @param sc Show for the third element of the tuple.
   * @return A show instance for the {@link P3 tuple-3} type.
   */
  public static  Show> p3Show(final Show sa, final Show sb, final Show sc) {
    return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',')
        .append(sc.show(p._3())).snoc(')'));
  }

  /**
   * A show instance for the {@link P4 tuple-4} type.
   *
   * @param sa Show for the first element of the tuple.
   * @param sb Show for the second element of the tuple.
   * @param sc Show for the third element of the tuple.
   * @param sd Show for the fourth element of the tuple.
   * @return A show instance for the {@link P4 tuple-4} type.
   */
  public static  Show> p4Show(final Show sa, final Show sb,
                                                         final Show sc, final Show sd) {
    return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',')
        .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(')'));
  }

  /**
   * A show instance for the {@link P5 tuple-5} type.
   *
   * @param sa Show for the first element of the tuple.
   * @param sb Show for the second element of the tuple.
   * @param sc Show for the third element of the tuple.
   * @param sd Show for the fourth element of the tuple.
   * @param se Show for the fifth element of the tuple.
   * @return A show instance for the {@link P5 tuple-5} type.
   */
  public static  Show> p5Show(final Show sa, final Show sb,
                                                               final Show sc, final Show sd, final Show se) {
    return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',')
        .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',').append(se.show(p._5())).snoc(')'));
  }

  /**
   * A show instance for the {@link P6 tuple-6} type.
   *
   * @param sa Show for the first element of the tuple.
   * @param sb Show for the second element of the tuple.
   * @param sc Show for the third element of the tuple.
   * @param sd Show for the fourth element of the tuple.
   * @param se Show for the fifth element of the tuple.
   * @param sf Show for the sixth element of the tuple.
   * @return A show instance for the {@link P6 tuple-6} type.
   */
  public static  Show> p6Show(final Show sa, final Show sb,
                                                                       final Show sc, final Show sd,
                                                                       final Show se, final Show sf) {
    return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',')
        .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',')
        .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(')'));
  }

  /**
   * A show instance for the {@link P7 tuple-7} type.
   *
   * @param sa Show for the first element of the tuple.
   * @param sb Show for the second element of the tuple.
   * @param sc Show for the third element of the tuple.
   * @param sd Show for the fourth element of the tuple.
   * @param se Show for the fifth element of the tuple.
   * @param sf Show for the sixth element of the tuple.
   * @param sg Show for the seventh element of the tuple.
   * @return A show instance for the {@link P7 tuple-7} type.
   */
  public static  Show> p7Show(final Show sa, final Show sb,
                                                                             final Show sc, final Show sd,
                                                                             final Show se, final Show sf,
                                                                             final Show sg) {
    return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',')
        .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',')
        .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(',').append(sg.show(p._7())).snoc(')'));
  }

  /**
   * A show instance for the {@link P8 tuple-8} type.
   *
   * @param sa Show for the first element of the tuple.
   * @param sb Show for the second element of the tuple.
   * @param sc Show for the third element of the tuple.
   * @param sd Show for the fourth element of the tuple.
   * @param se Show for the fifth element of the tuple.
   * @param sf Show for the sixth element of the tuple.
   * @param sg Show for the seventh element of the tuple.
   * @param sh Show for the eighth element of the tuple.
   * @return A show instance for the {@link P8 tuple-8} type.
   */
  public static  Show> p8Show(final Show sa, final Show sb,
                                                                                   final Show sc, final Show sd,
                                                                                   final Show se, final Show sf,
                                                                                   final Show sg, final Show sh) {
    return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',')
        .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',')
        .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(',')
        .append(sg.show(p._7())).snoc(',').append(sh.show(p._8())).snoc(')'));
  }

  public static  Show> priorityQueueShow(Show sk, Show sv) {
    return show(pq -> {
      return streamShow(p2MapShow(sk, sv), "PriorityQueue(", ", ", ")").show(pq.toStream());
    });
  }

  /**
   * A show instance for a vector-2.
   *
   * @param ea A show for the elements of the vector.
   * @return A show instance for a vector-2.
   */
  public static  Show> v2Show(final Show ea) {
    return streamShow(ea, "V2(", ",", ")").contramap(V2.toStream_());
  }

  /**
   * A show instance for a vector-3.
   *
   * @param ea A show for the elements of the vector.
   * @return A show instance for a vector-3.
   */
  public static  Show> v3Show(final Show ea) {
    return streamShow(ea, "V3(", ",", ")").contramap(V3.toStream_());
  }

  /**
   * A show instance for a vector-4.
   *
   * @param ea A show for the elements of the vector.
   * @return A show instance for a vector-4.
   */
  public static  Show> v4Show(final Show ea) {
    return streamShow(ea, "V4(", ",", ")").contramap(V4.toStream_());
  }

  /**
   * A show instance for a vector-5.
   *
   * @param ea A show for the elements of the vector.
   * @return A show instance for a vector-5.
   */
  public static  Show> v5Show(final Show ea) {
    return streamShow(ea, "V5(", ",", ")").contramap(V5.toStream_());
  }

  /**
   * A show instance for a vector-6.
   *
   * @param ea A show for the elements of the vector.
   * @return A show instance for a vector-6.
   */
  public static  Show> v6Show(final Show ea) {
    return streamShow(ea, "V6(", ",", ")").contramap(V6.toStream_());
  }

  /**
   * A show instance for a vector-7.
   *
   * @param ea A show for the elements of the vector.
   * @return A show instance for a vector-7.
   */
  public static  Show> v7Show(final Show ea) {
    return streamShow(ea, "V7(", ",", ")").contramap(V7.toStream_());
  }

  /**
   * A show instance for a vector-8.
   *
   * @param ea A show for the elements of the vector.
   * @return A show instance for a vector-8.
   */
  public static  Show> v8Show(final Show ea) {
    return streamShow(ea, "V8(", ",", ")").contramap(V8.toStream_());
  }

  /**
   * A show instance for natural numbers.
   */
  public static final Show naturalShow = bigintShow.contramap(Natural::bigIntegerValue);

  /**
   * A show instance for streams that splits into lines.
   *
   * @param sa A show instance for the elements of a stream.
   * @return A show instance for streams that splits into lines.
   */
  public static  Show> unlineShow(final Show sa) {
    return show(as -> join(as.map(sa.show_()).intersperse(fromString("\n"))));
  }

  /**
   * A show instance for lazy strings.
   */
  public static final Show lazyStringShow = show(LazyString::toStream);

  /**
   * A show instance for the empty heterogeneous Stream.
   */
  public static final Show HListShow = showS(Function.constant("Nil"));

  /**
   * A show instance for heterogeneous Streams.
   *
   * @param e A show instance for the first element of the Stream.
   * @param l A show instance for the rest of the Stream.
   * @return a show instance for heterogeneous Streams.
   */
  public static > Show> HListShow(final Show e, final Show l) {
    return show(c -> fromString("HList(").append(e.show(c.head())).append(l.show(c.tail())).append(fromString(")")));
  }
}