001    package fj.pre;
002    
003    import static fj.Function.compose;
004    import fj.Class;
005    import fj.F;
006    import fj.Function;
007    import fj.P1;
008    import fj.P2;
009    import fj.P3;
010    import fj.P4;
011    import fj.P5;
012    import fj.P6;
013    import fj.P7;
014    import fj.P8;
015    import fj.Unit;
016    import static fj.P.p;
017    import static fj.Unit.unit;
018    import fj.data.hlist.HList;
019    import fj.data.*;
020    import static fj.data.Stream.*;
021    import fj.data.vector.V2;
022    import fj.data.vector.V3;
023    import fj.data.vector.V4;
024    import fj.data.vector.V5;
025    import fj.data.vector.V6;
026    import fj.data.vector.V7;
027    import fj.data.vector.V8;
028    
029    import java.math.BigInteger;
030    import java.math.BigDecimal;
031    import java.util.Arrays;
032    
033    /**
034     * Renders an object for display.
035     *
036     * @version %build.number%<br>
037     *          <ul>
038     *          <li>$LastChangedRevision: 152 $</li>
039     *          <li>$LastChangedDate: 2009-05-30 18:27:20 +1000 (Sat, 30 May 2009) $</li>
040     *          </ul>
041     */
042    public final class Show<A> {
043      private final F<A, Stream<Character>> f;
044    
045      private Show(final F<A, Stream<Character>> f) {
046        this.f = f;
047      }
048    
049      /**
050       * Maps the given function across this show as a contra-variant functor.
051       *
052       * @param f The function to map.
053       * @return A new show.
054       */
055      public <B> Show<B> comap(final F<B, A> f) {
056        return show(compose(this.f, f));
057      }
058    
059      /**
060       * Returns the display rendering of the given argument.
061       *
062       * @param a The argument to display.
063       * @return The display rendering of the given argument.
064       */
065      public Stream<Character> show(final A a) {
066        return f.f(a);
067      }
068    
069      /**
070       * Returns the display rendering of the given argument.
071       *
072       * @param a The argument to display.
073       * @return The display rendering of the given argument.
074       */
075      public List<Character> showl(final A a) {
076        return show(a).toList();
077      }
078    
079      /**
080       * Returns the display rendering of the given argument as a <code>String</code>.
081       *
082       * @param a The argument to display.
083       * @return The display rendering of the given argument as a <code>String</code>.
084       */
085      public String showS(final A a) {
086        return Stream.asString(show(a));
087      }
088    
089      /**
090       * Returns the transformation equivalent to this show.
091       *
092       * @return the transformation equivalent to this show.
093       */
094      public F<A, String> showS_() {
095        return new F<A, String>() {
096          public String f(final A a) {
097            return showS(a);
098          }
099        };
100      }
101    
102      /**
103       * Returns the transformation equivalent to this show.
104       *
105       * @return the transformation equivalent to this show.
106       */
107      public F<A, Stream<Character>> show_() {
108        return f;
109      }
110    
111      /**
112       * Prints the given argument to the standard output stream with a new line.
113       *
114       * @param a The argument to print.
115       * @return The unit value.
116       */
117      public Unit println(final A a) {
118        print(a);
119        System.out.println();
120        return unit();
121      }
122    
123      /**
124       * Prints the given argument to the standard output stream.
125       *
126       * @param a The argument to print.
127       * @return The unit value.
128       */
129      public Unit print(final A a) {
130        final char[] buffer = new char[8192];
131        int c = 0;
132        for (Stream<Character> cs = show(a); cs.isNotEmpty(); cs = cs.tail()._1()) {
133          buffer[c] = cs.head();
134          c++;
135          if (c == 8192) {
136            System.out.print(buffer);
137            c = 0;
138          }
139        }
140        System.out.print(Arrays.copyOfRange(buffer, 0, c));
141        return unit();
142      }
143    
144      /**
145       * Prints the given argument to the standard error stream with a new line.
146       *
147       * @param a The argument to print.
148       */
149      public void printlnE(final A a) {
150        System.err.println(showS(a));
151      }
152    
153      /**
154       * Returns a show instance using the given function.
155       *
156       * @param f The function to use for the returned show instance.
157       * @return A show instance.
158       */
159      public static <A> Show<A> show(final F<A, Stream<Character>> f) {
160        return new Show<A>(f);
161      }
162    
163      /**
164       * Returns a show instance using the given function.
165       *
166       * @param f The function to use for the returned show instance.
167       * @return A show instance.
168       */
169      public static <A> Show<A> showS(final F<A, String> f) {
170        return new Show<A>(new F<A, Stream<Character>>() {
171          public Stream<Character> f(final A a) {
172            return fromString(f.f(a));
173          }
174        });
175      }
176    
177      /**
178       * Returns a show instance that uses {@link Object#toString()} to perform the display rendering.
179       *
180       * @return A show instance that uses {@link Object#toString()} to perform the display rendering.
181       */
182      public static <A> Show<A> anyShow() {
183        return new Show<A>(new F<A, Stream<Character>>() {
184          public Stream<Character> f(final A a) {
185            return Stream.fromString(a.toString());
186          }
187        });
188      }
189    
190      /**
191       * A show instance for the <code>boolean</code> type.
192       */
193      public static final Show<Boolean> booleanShow = anyShow();
194    
195      /**
196       * A show instance for the <code>byte</code> type.
197       */
198      public static final Show<Byte> byteShow = anyShow();
199    
200      /**
201       * A show instance for the <code>char</code> type.
202       */
203      public static final Show<Character> charShow = anyShow();
204    
205      /**
206       * A show instance for the <code>double</code> type.
207       */
208      public static final Show<Double> doubleShow = anyShow();
209    
210      /**
211       * A show instance for the <code>float</code> type.
212       */
213      public static final Show<Float> floatShow = anyShow();
214    
215      /**
216       * A show instance for the <code>int</code> type.
217       */
218      public static final Show<Integer> intShow = anyShow();
219    
220      /**
221       * A show instance for the <code>BigInteger</code> type.
222       */
223      public static final Show<BigInteger> bigintShow = anyShow();
224    
225      /**
226       * A show instance for the <code>BigDecimal</code> type.
227       */
228      public static final Show<BigDecimal> bigdecimalShow = anyShow();
229    
230      /**
231       * A show instance for the <code>long</code> type.
232       */
233      public static final Show<Long> longShow = anyShow();
234    
235      /**
236       * A show instance for the <code>short</code> type.
237       */
238      public static final Show<Short> shortShow = anyShow();
239    
240      /**
241       * A show instance for the {@link String} type.
242       */
243      public static final Show<String> stringShow = anyShow();
244    
245      /**
246       * A show instance for the {@link StringBuffer} type.
247       */
248      public static final Show<StringBuffer> stringBufferShow = anyShow();
249    
250      /**
251       * A show instance for the {@link StringBuilder} type.
252       */
253      public static final Show<StringBuilder> stringBuilderShow = anyShow();
254    
255      /**
256       * A show instance for the {@link Option} type.
257       *
258       * @param sa Show for the element of the option.
259       * @return A show instance for the {@link Option} type.
260       */
261      public static <A> Show<Option<A>> optionShow(final Show<A> sa) {
262        return new Show<Option<A>>(new F<Option<A>, Stream<Character>>() {
263          public Stream<Character> f(final Option<A> o) {
264            return o.isNone() ?
265                   fromString("None") :
266                   fromString("Some(").append(sa.f.f(o.some())).append(single(')'));
267          }
268        });
269      }
270    
271      /**
272       * A show instance for the {@link Either} type.
273       *
274       * @param sa Show for the left side of the {@link Either}.
275       * @param sb Show for the right side of the {@link Either}.
276       * @return A show instance for the {@link Either} type.
277       */
278      public static <A, B> Show<Either<A, B>> eitherShow(final Show<A> sa, final Show<B> sb) {
279        return new Show<Either<A, B>>(new F<Either<A, B>, Stream<Character>>() {
280          public Stream<Character> f(final Either<A, B> e) {
281            return e.isLeft() ?
282                   fromString("Left(").append(sa.f.f(e.left().value())).append(single(')')) :
283                   fromString("Right(").append(sb.f.f(e.right().value())).append(single(')'));
284          }
285        });
286      }
287    
288      /**
289       * A show instance for the {@link Validation} type.
290       *
291       * @param sa Show for the fail side of the {@link Validation}.
292       * @param sb Show for the success side of the {@link Validation}.
293       * @return A show instance for the {@link Validation} type.
294       */
295      public static <A, B> Show<Validation<A, B>> validationShow(final Show<A> sa, final Show<B> sb) {
296        return new Show<Validation<A, B>>(new F<Validation<A, B>, Stream<Character>>() {
297          public Stream<Character> f(final Validation<A, B> v) {
298            return v.isFail() ?
299                   fromString("Fail(").append(sa.f.f(v.fail())).append(single(')')) :
300                   fromString("Success(").append(sb.f.f(v.success())).append(single(')'));
301          }
302        });
303      }
304    
305      /**
306       * A show instance for the {@link Stream} type.
307       *
308       * @param sa Show for the elements of the Stream.
309       * @return A show instance for the {@link Stream} type.
310       */
311      public static <A> Show<List<A>> listShow(final Show<A> sa) {
312        return new Show<List<A>>(new F<List<A>, Stream<Character>>() {
313          public Stream<Character> f(final List<A> as) {
314            return streamShow(sa).show(as.toStream());
315          }
316        });
317      }
318    
319      /**
320       * A show instance for the {@link NonEmptyList} type.
321       *
322       * @param sa Show for the elements of the non-empty Stream.
323       * @return A show instance for the {@link NonEmptyList} type.
324       */
325      public static <A> Show<NonEmptyList<A>> nonEmptyListShow(final Show<A> sa) {
326        return listShow(sa).comap(NonEmptyList.<A>toList_());
327      }
328    
329      /**
330       * A show instance for the {@link Tree} type.
331       *
332       * @param sa Show for the elements of the tree.
333       * @return A show instance for the {@link Tree} type.
334       */
335      public static <A> Show<Tree<A>> treeShow(final Show<A> sa) {
336        return new Show<Tree<A>>(new F<Tree<A>, Stream<Character>>() {
337          public Stream<Character> f(final Tree<A> a) {
338            Stream<Character> b = sa.f.f(a.root())
339                .append(p1Show(streamShow(treeShow(sa))).f.f(a.subForest()))
340                .snoc(')');
341            return cons('(', p(b));
342          }
343        });
344      }
345    
346      /**
347       * A show instance for the {@link Stream} type.
348       *
349       * @param sa Show for the elements of the stream.
350       * @return A show instance for the {@link Stream} type.
351       */
352      public static <A> Show<Stream<A>> streamShow(final Show<A> sa) {
353        return new Show<Stream<A>>(new F<Stream<A>, Stream<Character>>() {
354          public Stream<Character> f(final Stream<A> as) {
355            return join(as.map(sa.show_()).intersperse(fromString(",")).cons(fromString("<")).snoc(p(fromString(">"))));
356          }
357        });
358      }
359    
360      /**
361       * A show instance for the {@link Array} type.
362       *
363       * @param sa Show for the elements of the array.
364       * @return A show instance for the {@link Array} type.
365       */
366      public static <A> Show<Array<A>> arrayShow(final Show<A> sa) {
367        return new Show<Array<A>>(new F<Array<A>, Stream<Character>>() {
368          public Stream<Character> f(final Array<A> as) {
369            Stream<Character> b = nil();
370    
371            for (int i = 0; i < as.length(); i++) {
372              b = b.append(sa.f.f(as.get(i)));
373    
374              if (i != as.length() - 1)
375                b = b.snoc(',');
376            }
377    
378            b = b.snoc('}');
379    
380            return cons('{', p(b));
381          }
382        });
383      }
384    
385      /**
386       * A show instance for the {@link Class} type.
387       *
388       * @return A show instance for the {@link Class} type.
389       */
390      public static <A> Show<Class<A>> classShow() {
391        return new Show<Class<A>>(new F<fj.Class<A>, Stream<Character>>() {
392          public Stream<Character> f(final Class<A> c) {
393            return anyShow().show(c.clas());
394          }
395        });
396      }
397    
398      /**
399       * A show instance for the {@link P1 tuple-1} type.
400       *
401       * @param sa Show for the first element of the tuple.
402       * @return A show instance for the {@link P1 tuple-1} type.
403       */
404      public static <A> Show<P1<A>> p1Show(final Show<A> sa) {
405        return new Show<P1<A>>(new F<P1<A>, Stream<Character>>() {
406          public Stream<Character> f(final P1<A> p) {
407            return cons('(', p(sa.show(p._1()))).snoc(')');
408          }
409        });
410      }
411    
412      /**
413       * A show instance for the {@link P2 tuple-2} type.
414       *
415       * @param sa Show for the first element of the tuple.
416       * @param sb Show for the second element of the tuple.
417       * @return A show instance for the {@link P2 tuple-2} type.
418       */
419      public static <A, B> Show<P2<A, B>> p2Show(final Show<A> sa, final Show<B> sb) {
420        return new Show<P2<A, B>>(new F<P2<A, B>, Stream<Character>>() {
421          public Stream<Character> f(final P2<A, B> p) {
422            return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(')');
423          }
424        });
425      }
426    
427      /**
428       * A show instance for the {@link P3 tuple-3} type.
429       *
430       * @param sa Show for the first element of the tuple.
431       * @param sb Show for the second element of the tuple.
432       * @param sc Show for the third element of the tuple.
433       * @return A show instance for the {@link P3 tuple-3} type.
434       */
435      public static <A, B, C> Show<P3<A, B, C>> p3Show(final Show<A> sa, final Show<B> sb, final Show<C> sc) {
436        return new Show<P3<A, B, C>>(new F<P3<A, B, C>, Stream<Character>>() {
437          public Stream<Character> f(final P3<A, B, C> p) {
438            return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',')
439                .append(sc.show(p._3())).snoc(')');
440          }
441        });
442      }
443    
444      /**
445       * A show instance for the {@link P4 tuple-4} type.
446       *
447       * @param sa Show for the first element of the tuple.
448       * @param sb Show for the second element of the tuple.
449       * @param sc Show for the third element of the tuple.
450       * @param sd Show for the fourth element of the tuple.
451       * @return A show instance for the {@link P4 tuple-4} type.
452       */
453      public static <A, B, C, D> Show<P4<A, B, C, D>> p4Show(final Show<A> sa, final Show<B> sb,
454                                                             final Show<C> sc, final Show<D> sd) {
455        return new Show<P4<A, B, C, D>>(new F<P4<A, B, C, D>, Stream<Character>>() {
456          public Stream<Character> f(final P4<A, B, C, D> p) {
457            return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',')
458                .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(')');
459          }
460        });
461      }
462    
463      /**
464       * A show instance for the {@link P5 tuple-5} type.
465       *
466       * @param sa Show for the first element of the tuple.
467       * @param sb Show for the second element of the tuple.
468       * @param sc Show for the third element of the tuple.
469       * @param sd Show for the fourth element of the tuple.
470       * @param se Show for the fifth element of the tuple.
471       * @return A show instance for the {@link P5 tuple-5} type.
472       */
473      public static <A, B, C, D, E> Show<P5<A, B, C, D, E>> p5Show(final Show<A> sa, final Show<B> sb,
474                                                                   final Show<C> sc, final Show<D> sd, final Show<E> se) {
475        return new Show<P5<A, B, C, D, E>>(new F<P5<A, B, C, D, E>, Stream<Character>>() {
476          public Stream<Character> f(final P5<A, B, C, D, E> p) {
477            return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',')
478                .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',').append(se.show(p._5())).snoc(')');
479          }
480        });
481      }
482    
483      /**
484       * A show instance for the {@link P6 tuple-6} type.
485       *
486       * @param sa Show for the first element of the tuple.
487       * @param sb Show for the second element of the tuple.
488       * @param sc Show for the third element of the tuple.
489       * @param sd Show for the fourth element of the tuple.
490       * @param se Show for the fifth element of the tuple.
491       * @param sf Show for the sixth element of the tuple.
492       * @return A show instance for the {@link P6 tuple-6} type.
493       */
494      public static <A, B, C, D, E, F$> Show<P6<A, B, C, D, E, F$>> p6Show(final Show<A> sa, final Show<B> sb,
495                                                                           final Show<C> sc, final Show<D> sd,
496                                                                           final Show<E> se, final Show<F$> sf) {
497        return new Show<P6<A, B, C, D, E, F$>>(new F<P6<A, B, C, D, E, F$>, Stream<Character>>() {
498          public Stream<Character> f(final P6<A, B, C, D, E, F$> p) {
499            return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',')
500                .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',')
501                .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(')');
502          }
503        });
504      }
505    
506      /**
507       * A show instance for the {@link P7 tuple-7} type.
508       *
509       * @param sa Show for the first element of the tuple.
510       * @param sb Show for the second element of the tuple.
511       * @param sc Show for the third element of the tuple.
512       * @param sd Show for the fourth element of the tuple.
513       * @param se Show for the fifth element of the tuple.
514       * @param sf Show for the sixth element of the tuple.
515       * @param sg Show for the seventh element of the tuple.
516       * @return A show instance for the {@link P7 tuple-7} type.
517       */
518      public static <A, B, C, D, E, F$, G> Show<P7<A, B, C, D, E, F$, G>> p7Show(final Show<A> sa, final Show<B> sb,
519                                                                                 final Show<C> sc, final Show<D> sd,
520                                                                                 final Show<E> se, final Show<F$> sf,
521                                                                                 final Show<G> sg) {
522        return new Show<P7<A, B, C, D, E, F$, G>>(new F<P7<A, B, C, D, E, F$, G>, Stream<Character>>() {
523          public Stream<Character> f(final P7<A, B, C, D, E, F$, G> p) {
524            return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',')
525                .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',')
526                .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(',').append(sg.show(p._7())).snoc(')');
527          }
528        });
529      }
530    
531      /**
532       * A show instance for the {@link P8 tuple-8} type.
533       *
534       * @param sa Show for the first element of the tuple.
535       * @param sb Show for the second element of the tuple.
536       * @param sc Show for the third element of the tuple.
537       * @param sd Show for the fourth element of the tuple.
538       * @param se Show for the fifth element of the tuple.
539       * @param sf Show for the sixth element of the tuple.
540       * @param sg Show for the seventh element of the tuple.
541       * @param sh Show for the eighth element of the tuple.
542       * @return A show instance for the {@link P8 tuple-8} type.
543       */
544      public static <A, B, C, D, E, F$, G, H> Show<P8<A, B, C, D, E, F$, G, H>> p8Show(final Show<A> sa, final Show<B> sb,
545                                                                                       final Show<C> sc, final Show<D> sd,
546                                                                                       final Show<E> se, final Show<F$> sf,
547                                                                                       final Show<G> sg, final Show<H> sh) {
548        return new Show<P8<A, B, C, D, E, F$, G, H>>(new F<P8<A, B, C, D, E, F$, G, H>, Stream<Character>>() {
549          public Stream<Character> f(final P8<A, B, C, D, E, F$, G, H> p) {
550            return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',')
551                .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',')
552                .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(',')
553                .append(sg.show(p._7())).snoc(',').append(sh.show(p._8())).snoc(')');
554          }
555        });
556      }
557    
558      /**
559       * A show instance for a vector-2.
560       *
561       * @param ea A show for the elements of the vector.
562       * @return A show instance for a vector-2.
563       */
564      public static <A> Show<V2<A>> v2Show(final Show<A> ea) {
565        return streamShow(ea).comap(V2.<A>toStream_());
566      }
567    
568      /**
569       * A show instance for a vector-3.
570       *
571       * @param ea A show for the elements of the vector.
572       * @return A show instance for a vector-3.
573       */
574      public static <A> Show<V3<A>> v3Show(final Show<A> ea) {
575        return streamShow(ea).comap(V3.<A>toStream_());
576      }
577    
578      /**
579       * A show instance for a vector-4.
580       *
581       * @param ea A show for the elements of the vector.
582       * @return A show instance for a vector-4.
583       */
584      public static <A> Show<V4<A>> v4Show(final Show<A> ea) {
585        return streamShow(ea).comap(V4.<A>toStream_());
586      }
587    
588      /**
589       * A show instance for a vector-5.
590       *
591       * @param ea A show for the elements of the vector.
592       * @return A show instance for a vector-5.
593       */
594      public static <A> Show<V5<A>> v5Show(final Show<A> ea) {
595        return streamShow(ea).comap(V5.<A>toStream_());
596      }
597    
598      /**
599       * A show instance for a vector-6.
600       *
601       * @param ea A show for the elements of the vector.
602       * @return A show instance for a vector-6.
603       */
604      public static <A> Show<V6<A>> v6Show(final Show<A> ea) {
605        return streamShow(ea).comap(V6.<A>toStream_());
606      }
607    
608      /**
609       * A show instance for a vector-7.
610       *
611       * @param ea A show for the elements of the vector.
612       * @return A show instance for a vector-7.
613       */
614      public static <A> Show<V7<A>> v7Show(final Show<A> ea) {
615        return streamShow(ea).comap(V7.<A>toStream_());
616      }
617    
618      /**
619       * A show instance for a vector-8.
620       *
621       * @param ea A show for the elements of the vector.
622       * @return A show instance for a vector-8.
623       */
624      public static <A> Show<V8<A>> v8Show(final Show<A> ea) {
625        return streamShow(ea).comap(V8.<A>toStream_());
626      }
627    
628      /**
629       * A show instance for natural numbers.
630       */
631      public static final Show<Natural> naturalShow = bigintShow.comap(new F<Natural, BigInteger>() {
632        public BigInteger f(final Natural natural) {
633          return natural.bigIntegerValue();
634        }
635      });
636    
637      /**
638       * A show instance for streams that splits into lines.
639       *
640       * @param sa A show instance for the elements of a stream.
641       * @return A show instance for streams that splits into lines.
642       */
643      public static <A> Show<Stream<A>> unlineShow(final Show<A> sa) {
644        return new Show<Stream<A>>(new F<Stream<A>, Stream<Character>>() {
645          public Stream<Character> f(final Stream<A> as) {
646            return join(as.map(sa.show_()).intersperse(fromString("\n")));
647          }
648        });
649      }
650    
651      /**
652       * A show instance for lazy strings.
653       */
654      public static final Show<LazyString> lazyStringShow = show(new F<LazyString, Stream<Character>>() {
655        public Stream<Character> f(final LazyString string) {
656          return string.toStream();
657        }
658      });
659    
660      /**
661       * A show instance for the empty heterogeneous Stream.
662       */
663      public static final Show<HList.HNil> HListShow = showS(Function.<HList.HNil, String>constant("Nil"));
664    
665      /**
666       * A show instance for heterogeneous Streams.
667       *
668       * @param e A show instance for the first element of the Stream.
669       * @param l A show instance for the rest of the Stream.
670       * @return a show instance for heterogeneous Streams.
671       */
672      public static <E, L extends HList<L>> Show<HList.HCons<E, L>> HListShow(final Show<E> e, final Show<L> l) {
673        return show(new F<HList.HCons<E, L>, Stream<Character>>() {
674          public Stream<Character> f(final HList.HCons<E, L> c) {
675            return e.show(c.head()).cons('[').append(l.show(c.tail())).snoc(']');
676          }
677        });
678      }
679    }