package fj; import fj.data.Array; import fj.data.Either; import fj.data.LazyString; import fj.data.List; import fj.data.Natural; import fj.data.NonEmptyList; import fj.data.Option; import fj.data.Stream; import fj.data.Tree; import fj.data.Validation; 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.nil; 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 comap(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 new F() { public String f(final A a) { return showS(a); } }; } /** * 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 new Show(new F>() { public Stream f(final A a) { return 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 new Show(new F>() { public Stream f(final A a) { return Stream.fromString(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 new Show>(new F, Stream>() { public Stream f(final Option o) { return 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 new Show>(new F, Stream>() { public Stream f(final Either e) { return 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 new Show>(new F, Stream>() { public Stream f(final Validation v) { return 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 new Show>(new F, Stream>() { public Stream f(final List as) { return streamShow(sa).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).comap(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 new Show>(new F, Stream>() { public Stream f(final Tree a) { final Stream b = sa.f.f(a.root()) .append(p1Show(streamShow(treeShow(sa))).f.f(a.subForest())) .snoc(')'); return cons('(', p(b)); } }); } /** * 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 new Show>(new F, Stream>() { public Stream f(final Stream as) { return join(as.map(sa.show_()).intersperse(fromString(",")).cons(fromString("<")).snoc(p(fromString(">")))); } }); } /** * 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 new Show>(new F, Stream>() { public Stream f(final Array as) { Stream b = nil(); for (int i = 0; i < as.length(); i++) { b = b.append(sa.f.f(as.get(i))); if (i != as.length() - 1) b = b.snoc(','); } b = b.snoc('}'); return cons('{', p(b)); } }); } /** * A show instance for the {@link Class} type. * * @return A show instance for the {@link Class} type. */ public static Show> classShow() { return new Show>(new F, Stream>() { public Stream f(final Class c) { return 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 new Show>(new F, Stream>() { public Stream f(final P1 p) { return 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 new Show>(new F, Stream>() { public Stream f(final P2 p) { return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(')'); } }); } /** * 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 new Show>(new F, Stream>() { public Stream f(final P3 p) { return 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 new Show>(new F, Stream>() { public Stream f(final P4 p) { return 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 new Show>(new F, Stream>() { public Stream f(final P5 p) { return 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 new Show>(new F, Stream>() { public Stream f(final P6 p) { return 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 new Show>(new F, Stream>() { public Stream f(final P7 p) { return 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 new Show>(new F, Stream>() { public Stream f(final P8 p) { return 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(')'); } }); } /** * 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).comap(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).comap(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).comap(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).comap(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).comap(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).comap(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).comap(V8.toStream_()); } /** * A show instance for natural numbers. */ public static final Show naturalShow = bigintShow.comap(new F() { public BigInteger f(final Natural natural) { return 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 new Show>(new F, Stream>() { public Stream f(final Stream as) { return join(as.map(sa.show_()).intersperse(fromString("\n"))); } }); } /** * A show instance for lazy strings. */ public static final Show lazyStringShow = show(new F>() { public Stream f(final LazyString string) { return string.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(new F, Stream>() { public Stream f(final HList.HCons c) { return e.show(c.head()).cons('[').append(l.show(c.tail())).snoc(']'); } }); } }