001    package fj;
002    
003    import static fj.F2W.$$;
004    import static fj.Function.compose;
005    import static fj.P.p;
006    import fj.control.parallel.Actor;
007    import fj.control.parallel.Promise;
008    import fj.control.parallel.Strategy;
009    import fj.data.Array;
010    import fj.data.Either;
011    import fj.data.IterableW;
012    import fj.data.List;
013    import fj.data.NonEmptyList;
014    import fj.data.Option;
015    import fj.data.Set;
016    import fj.data.Stream;
017    import fj.data.Tree;
018    import fj.data.TreeZipper;
019    import fj.data.Validation;
020    import fj.data.Zipper;
021    import static fj.data.Stream.iterableStream;
022    import static fj.data.Zipper.fromStream;
023    import fj.pre.Equal;
024    import fj.pre.Hash;
025    import fj.pre.Monoid;
026    import fj.pre.Ord;
027    import fj.pre.Show;
028    
029    import java.util.ArrayList;
030    import java.util.LinkedList;
031    import java.util.PriorityQueue;
032    import java.util.TreeSet;
033    import java.util.concurrent.ArrayBlockingQueue;
034    import java.util.concurrent.ConcurrentLinkedQueue;
035    import java.util.concurrent.CopyOnWriteArrayList;
036    import java.util.concurrent.CopyOnWriteArraySet;
037    import java.util.concurrent.LinkedBlockingQueue;
038    import java.util.concurrent.PriorityBlockingQueue;
039    import java.util.concurrent.SynchronousQueue;
040    
041    /**
042     * A wrapper for functions of arity 1, that decorates them with higher-order functions.
043     */
044    public final class FW<A, B> implements F<A, B> {
045      private final F<A, B> f;
046    
047      private FW(final F<A, B> f) {
048        this.f = f;
049      }
050    
051      /**
052       * Wraps the given function, decorating it with higher-order functions.
053       *
054       * @param f A function to wrap.
055       * @return The given function, wrapped.
056       */
057      public static <A, B> FW<A, B> $(final F<A, B> f) {
058        return new FW<A, B>(f);
059      }
060    
061      /**
062       * First-class constructor for FW.
063       *
064       * @return A function that wraps a given function.
065       */
066      public static <A, B> FW<F<A, B>, FW<A, B>> $() {
067        return $(new F<F<A, B>, FW<A, B>>() {
068          public FW<A, B> f(final F<A, B> f) {
069            return $(f);
070          }
071        });
072      }
073    
074      /**
075       * Function application
076       *
077       * @param a The <code>A</code> to transform.
078       * @return The result of the transformation.
079       */
080      public B f(final A a) {
081        return f.f(a);
082      }
083    
084      /**
085       * Function composition
086       *
087       * @param g A function to compose with this one.
088       * @return The composed function such that this function is applied last.
089       */
090      public <C> FW<C, B> o(final F<C, A> g) {
091        return $(compose(f, g));
092      }
093    
094      /**
095       * First-class function composition
096       *
097       * @return A function that composes this function with another.
098       */
099      public <C> FW<F<C, A>, F<C, B>> o_() {
100        return $(new F<F<C, A>, F<C, B>>() {
101          public F<C, B> f(final F<C, A> g) {
102            return $(o(g));
103          }
104        });
105      }
106    
107      /**
108       * Function composition flipped.
109       *
110       * @param g A function with which to compose this one.
111       * @return The composed function such that this function is applied first.
112       */
113      public <C> FW<A, C> andThen(final F<B, C> g) {
114        return $(compose(g, this));
115      }
116    
117      /**
118       * First-class composition flipped.
119       *
120       * @return A function that invokes this function and then a given function on the result.
121       */
122      public <C> FW<F<B, C>, F<A, C>> andThen_() {
123        return $(new F<F<B, C>, F<A, C>>() {
124          public F<A, C> f(final F<B, C> g) {
125            return andThen(g);
126          }
127        });
128      }
129    
130      /**
131       * Simultaneously covaries and contravaries a function.
132       *
133       * @return A co- and contravariant function that invokes this function on its argument.
134       */
135      public FW<? super A, ? extends B> vary() {
136        return $(Function.vary(this));
137      }
138    
139      /**
140       * Binds a given function across this function (Reader Monad).
141       *
142       * @param g A function that takes the return value of this function as an argument, yielding a new function.
143       * @return A function that invokes this function on its argument and then the given function on the result.
144       */
145      public <C> FW<A, C> bind(final F<B, F<A, C>> g) {
146        return $(Function.bind(this, g));
147      }
148    
149      /**
150       * First-class function binding.
151       *
152       * @return A function that binds another function across this function.
153       */
154      public <C> FW<F<B, F<A, C>>, F<A, C>> bind() {
155        return $(new F<F<B, F<A, C>>, F<A, C>>() {
156          public F<A, C> f(final F<B, F<A, C>> bff) {
157            return bind(bff);
158          }
159        });
160      }
161    
162      /**
163       * Function application in an environment (Applicative Functor).
164       *
165       * @param g A function with the same argument type as this function, yielding a function that takes the return
166       *          value of this function.
167       * @return A new function that invokes the given function on its argument, yielding a new function that is then
168       *         applied to the result of applying this function to the argument.
169       */
170      public <C> FW<A, C> apply(final F<A, F<B, C>> g) {
171        return $(Function.apply(g, this));
172      }
173    
174      /**
175       * First-class function application in an environment.
176       *
177       * @return A function that applies a given function within the environment of this function.
178       */
179      public <C> FW<F<A, F<B, C>>, F<A, C>> apply() {
180        return $(new F<F<A, F<B, C>>, F<A, C>>() {
181          public F<A, C> f(final F<A, F<B, C>> aff) {
182            return apply(aff);
183          }
184        });
185      }
186    
187      /**
188       * Applies this function over the arguments of another function.
189       *
190       * @param g The function over whose arguments to apply this function.
191       * @return A new function that invokes this function on its arguments before invoking the given function.
192       */
193      public <C> FW<A, F<A, C>> on(final F<B, F<B, C>> g) {
194        return $(Function.on(g, this));
195      }
196    
197      /**
198       * First-class composition with a function of arity-2
199       *
200       * @return A function that applies this function over the arguments of a given function.
201       */
202      public <C> FW<F<B, F<B, C>>, F<A, F<A, C>>> on() {
203        return $(new F<F<B, F<B, C>>, F<A, F<A, C>>>() {
204          public F<A, F<A, C>> f(final F<B, F<B, C>> bff) {
205            return on(bff);
206          }
207        });
208      }
209    
210      /**
211       * Promotes this function so that it returns its result in a product-1. Kleisli arrow for P1.
212       *
213       * @return This function promoted to return its result in a product-1.
214       */
215      public FW<A, P1<B>> lazy() {
216        return $(P1.curry(f));
217      }
218    
219      /**
220       * Promotes this function to map over a product-1.
221       *
222       * @return This function promoted to map over a product-1.
223       */
224      public FW<P1<A>, P1<B>> mapP1() {
225        return $(P1.<A, B>fmap(f));
226      }
227    
228      /**
229       * Promotes this function so that it returns its result in an Option. Kleisli arrow for Option.
230       *
231       * @return This function promoted to return its result in an Option.
232       */
233      public FW<A, Option<B>> option() {
234        return $(Option.<B>some_()).o(f);
235      }
236    
237      /**
238       * Promotes this function to map over an optional value.
239       *
240       * @return This function promoted to map over an optional value.
241       */
242      public FW<Option<A>, Option<B>> mapOption() {
243        return $(Option.<A, B>map().f(f));
244      }
245    
246      /**
247       * Promotes this function so that it returns its result in a List. Kleisli arrow for List.
248       *
249       * @return This function promoted to return its result in a List.
250       */
251      public FW<A, List<B>> list() {
252        return $$(List.<B>cons()).flip().f(List.<B>nil()).o(f);
253      }
254    
255      /**
256       * Promotes this function to map over a List.
257       *
258       * @return This function promoted to map over a List.
259       */
260      public FW<List<A>, List<B>> mapList() {
261        return $(List.<A, B>map_().f(f));
262      }
263    
264      /**
265       * Promotes this function so that it returns its result in a Stream. Kleisli arrow for Stream.
266       *
267       * @return This function promoted to return its result in a Stream.
268       */
269      public FW<A, Stream<B>> stream() {
270        return $$(Stream.<B>cons()).flip().f(p(Stream.<B>nil())).o(f);
271      }
272    
273      /**
274       * Promotes this function to map over a Stream.
275       *
276       * @return This function promoted to map over a Stream.
277       */
278      public FW<Stream<A>, Stream<B>> mapStream() {
279        return $(Stream.<A, B>map_().f(f));
280      }
281    
282      /**
283       * Promotes this function so that it returns its result in an Array. Kleisli arrow for Array.
284       *
285       * @return This function promoted to return its result in an Array.
286       */
287      public FW<A, Array<B>> array() {
288        return $(new F<A, Array<B>>() {
289          public Array<B> f(final A a) {
290            return Array.single(f.f(a));
291          }
292        });
293      }
294    
295      /**
296       * Promotes this function to map over a Stream.
297       *
298       * @return This function promoted to map over a Stream.
299       */
300      public FW<Array<A>, Array<B>> mapArray() {
301        return $(Array.<A, B>map().f(f));
302      }
303    
304      /**
305       * Returns a function that comaps over a given actor.
306       *
307       * @return A function that comaps over a given actor.
308       */
309      public FW<Actor<B>, Actor<A>> comapActor() {
310        return $(new F<Actor<B>, Actor<A>>() {
311          public Actor<A> f(final Actor<B> actor) {
312            return actor.comap(f);
313          }
314        });
315      }
316    
317      /**
318       * Promotes this function to a concurrent function that returns a Promise of a value.
319       *
320       * @param s A parallel strategy for concurrent execution.
321       * @return A concurrent function that returns a Promise of a value.
322       */
323      public FW<A, Promise<B>> promise(final Strategy<Unit> s) {
324        return $(Promise.promise(s, f));
325      }
326    
327      /**
328       * Promotes this function to map over a Promise.
329       *
330       * @return This function promoted to map over Promises.
331       */
332      public FW<Promise<A>, Promise<B>> mapPromise() {
333        return $(new F<Promise<A>, Promise<B>>() {
334          public Promise<B> f(final Promise<A> promise) {
335            return promise.fmap(f);
336          }
337        });
338      }
339    
340      /**
341       * Promotes this function so that it returns its result on the left side of an Either.
342       * Kleisli arrow for the Either left projection.
343       *
344       * @return This function promoted to return its result on the left side of an Either.
345       */
346      public <C> FW<A, Either<B, C>> eitherLeft() {
347        return $(Either.<B, C>left_()).o(f);
348      }
349    
350      /**
351       * Promotes this function so that it returns its result on the right side of an Either.
352       * Kleisli arrow for the Either right projection.
353       *
354       * @return This function promoted to return its result on the right side of an Either.
355       */
356      public <C> FW<A, Either<C, B>> eitherRight() {
357        return $(Either.<C, B>right_()).o(f);
358      }
359    
360      /**
361       * Promotes this function to map over the left side of an Either.
362       *
363       * @return This function promoted to map over the left side of an Either.
364       */
365      public <X> FW<Either<A, X>, Either<B, X>> mapLeft() {
366        return $(Either.<A, X, B>leftMap_().f(f));
367      }
368    
369      /**
370       * Promotes this function to map over the right side of an Either.
371       *
372       * @return This function promoted to map over the right side of an Either.
373       */
374      public <X> FW<Either<X, A>, Either<X, B>> mapRight() {
375        return $(Either.<X, A, B>rightMap_().f(f));
376      }
377    
378      /**
379       * Returns a function that returns the left side of a given Either, or this function applied to the right side.
380       *
381       * @return a function that returns the left side of a given Either, or this function applied to the right side.
382       */
383      public FW<Either<B, A>, B> onLeft() {
384        return $(new F<Either<B, A>, B>() {
385          public B f(final Either<B, A> either) {
386            return either.left().on(f);
387          }
388        });
389      }
390    
391      /**
392       * Returns a function that returns the right side of a given Either, or this function applied to the left side.
393       *
394       * @return a function that returns the right side of a given Either, or this function applied to the left side.
395       */
396      public FW<Either<A, B>, B> onRight() {
397        return $(new F<Either<A, B>, B>() {
398          public B f(final Either<A, B> either) {
399            return either.right().on(f);
400          }
401        });
402      }
403    
404      /**
405       * Promotes this function to return its value in an Iterable.
406       *
407       * @return This function promoted to return its value in an Iterable.
408       */
409      public FW<A, IterableW<B>> iterable() {
410        return $(IterableW.<A, B>arrow().f(f));
411      }
412    
413      /**
414       * Promotes this function to map over Iterables.
415       *
416       * @return This function promoted to map over Iterables.
417       */
418      public FW<Iterable<A>, IterableW<B>> mapIterable() {
419        return $(IterableW.<A, B>map().f(f)).o(IterableW.<A, Iterable<A>>wrap());
420      }
421    
422      /**
423       * Promotes this function to return its value in a NonEmptyList.
424       *
425       * @return This function promoted to return its value in a NonEmptyList.
426       */
427      public FW<A, NonEmptyList<B>> nel() {
428        return $(NonEmptyList.<B>nel()).o(f);
429      }
430    
431      /**
432       * Promotes this function to map over a NonEmptyList.
433       *
434       * @return This function promoted to map over a NonEmptyList.
435       */
436      public FW<NonEmptyList<A>, NonEmptyList<B>> mapNel() {
437        return $(new F<NonEmptyList<A>, NonEmptyList<B>>() {
438          public NonEmptyList<B> f(final NonEmptyList<A> list) {
439            return list.map(f);
440          }
441        });
442      }
443    
444      /**
445       * Promotes this function to return its value in a Set.
446       *
447       * @param o An order for the set.
448       * @return This function promoted to return its value in a Set.
449       */
450      public FW<A, Set<B>> set(final Ord<B> o) {
451        return $(new F<A, Set<B>>() {
452          public Set<B> f(final A a) {
453            return Set.single(o, f.f(a));
454          }
455        });
456      }
457    
458      /**
459       * Promotes this function to map over a Set.
460       *
461       * @param o An order for the resulting set.
462       * @return This function promoted to map over a Set.
463       */
464      public FW<Set<A>, Set<B>> mapSet(final Ord<B> o) {
465        return $(new F<Set<A>, Set<B>>() {
466          public Set<B> f(final Set<A> set) {
467            return set.map(o, f);
468          }
469        });
470      }
471    
472      /**
473       * Promotes this function to return its value in a Tree.
474       *
475       * @return This function promoted to return its value in a Tree.
476       */
477      public FW<A, Tree<B>> tree() {
478        return $(new F<A, Tree<B>>() {
479          public Tree<B> f(final A a) {
480            return Tree.leaf(f.f(a));
481          }
482        });
483      }
484    
485      /**
486       * Promotes this function to map over a Tree.
487       *
488       * @return This function promoted to map over a Tree.
489       */
490      public FW<Tree<A>, Tree<B>> mapTree() {
491        return $(Tree.<A, B>fmap_().f(f));
492      }
493    
494      /**
495       * Returns a function that maps this function over a tree and folds it with the given monoid.
496       *
497       * @param m The monoid with which to fold the mapped tree.
498       * @return a function that maps this function over a tree and folds it with the given monoid.
499       */
500      public FW<Tree<A>, B> foldMapTree(final Monoid<B> m) {
501        return $(Tree.foldMap_(f, m));
502      }
503    
504      /**
505       * Promotes this function to return its value in a TreeZipper.
506       *
507       * @return This function promoted to return its value in a TreeZipper.
508       */
509      public FW<A, TreeZipper<B>> treeZipper() {
510        return tree().andThen(TreeZipper.<B>fromTree());
511      }
512    
513      /**
514       * Promotes this function to map over a TreeZipper.
515       *
516       * @return This function promoted to map over a TreeZipper.
517       */
518      public FW<TreeZipper<A>, TreeZipper<B>> mapTreeZipper() {
519        return $(new F<TreeZipper<A>, TreeZipper<B>>() {
520          public TreeZipper<B> f(final TreeZipper<A> zipper) {
521            return zipper.map(f);
522          }
523        });
524      }
525    
526      /**
527       * Promotes this function so that it returns its result on the failure side of a Validation.
528       * Kleisli arrow for the Validation failure projection.
529       *
530       * @return This function promoted to return its result on the failure side of a Validation.
531       */
532      public <C> FW<A, Validation<B, C>> fail() {
533        return $(new F<A, Validation<B, C>>() {
534          public Validation<B, C> f(final A a) {
535            return Validation.fail(f.f(a));
536          }
537        });
538      }
539    
540      /**
541       * Promotes this function so that it returns its result on the success side of an Validation.
542       * Kleisli arrow for the Validation success projection.
543       *
544       * @return This function promoted to return its result on the success side of an Validation.
545       */
546      public <C> FW<A, Validation<C, B>> success() {
547        return $(new F<A, Validation<C, B>>() {
548          public Validation<C, B> f(final A a) {
549            return Validation.success(f.f(a));
550          }
551        });
552      }
553    
554      /**
555       * Promotes this function to map over the failure side of a Validation.
556       *
557       * @return This function promoted to map over the failure side of a Validation.
558       */
559      public <X> FW<Validation<A, X>, Validation<B, X>> mapFail() {
560        return $(new F<Validation<A, X>, Validation<B, X>>() {
561          public Validation<B, X> f(final Validation<A, X> validation) {
562            return validation.f().map(f);
563          }
564        });
565      }
566    
567      /**
568       * Promotes this function to map over the success side of a Validation.
569       *
570       * @return This function promoted to map over the success side of a Validation.
571       */
572      public <X> FW<Validation<X, A>, Validation<X, B>> mapSuccess() {
573        return $(new F<Validation<X, A>, Validation<X, B>>() {
574          public Validation<X, B> f(final Validation<X, A> validation) {
575            return validation.map(f);
576          }
577        });
578      }
579    
580      /**
581       * Returns a function that returns the failure side of a given Validation,
582       * or this function applied to the success side.
583       *
584       * @return a function that returns the failure side of a given Validation,
585       *         or this function applied to the success side.
586       */
587      public FW<Validation<B, A>, B> onFail() {
588        return $(new F<Validation<B, A>, B>() {
589          public B f(final Validation<B, A> v) {
590            return v.f().on(f);
591          }
592        });
593      }
594    
595      /**
596       * Returns a function that returns the success side of a given Validation,
597       * or this function applied to the failure side.
598       *
599       * @return a function that returns the success side of a given Validation,
600       *         or this function applied to the failure side.
601       */
602      public FW<Validation<A, B>, B> onSuccess() {
603        return $(new F<Validation<A, B>, B>() {
604          public B f(final Validation<A, B> v) {
605            return v.on(f);
606          }
607        });
608      }
609    
610      /**
611       * Promotes this function to return its value in a Zipper.
612       *
613       * @return This function promoted to return its value in a Zipper.
614       */
615      public FW<A, Zipper<B>> zipper() {
616        return stream().andThen(new F<Stream<B>, Zipper<B>>() {
617          public Zipper<B> f(final Stream<B> stream) {
618            return fromStream(stream).some();
619          }
620        });
621      }
622    
623      /**
624       * Promotes this function to map over a Zipper.
625       *
626       * @return This function promoted to map over a Zipper.
627       */
628      public FW<Zipper<A>, Zipper<B>> mapZipper() {
629        return $(new F<Zipper<A>, Zipper<B>>() {
630          public Zipper<B> f(final Zipper<A> zipper) {
631            return zipper.map(f);
632          }
633        });
634      }
635    
636      /**
637       * Promotes this function to map over an Equal as a contravariant functor.
638       *
639       * @return This function promoted to map over an Equal as a contravariant functor.
640       */
641      public FW<Equal<B>, Equal<A>> comapEqual() {
642        return $(new F<Equal<B>, Equal<A>>() {
643          public Equal<A> f(final Equal<B> equal) {
644            return equal.comap(f);
645          }
646        });
647      }
648    
649      /**
650       * Promotes this function to map over a Hash as a contravariant functor.
651       *
652       * @return This function promoted to map over a Hash as a contravariant functor.
653       */
654      public FW<Hash<B>, Hash<A>> comapHash() {
655        return $(new F<Hash<B>, Hash<A>>() {
656          public Hash<A> f(final Hash<B> hash) {
657            return hash.comap(f);
658          }
659        });
660      }
661    
662      /**
663       * Promotes this function to map over a Show as a contravariant functor.
664       *
665       * @return This function promoted to map over a Show as a contravariant functor.
666       */
667      public FW<Show<B>, Show<A>> comapShow() {
668        return $(new F<Show<B>, Show<A>>() {
669          public Show<A> f(final Show<B> s) {
670            return s.comap(f);
671          }
672        });
673      }
674    
675      /**
676       * Promotes this function to map over the first element of a pair.
677       *
678       * @return This function promoted to map over the first element of a pair.
679       */
680      public <C> FW<P2<A, C>, P2<B, C>> mapFst() {
681        return $(P2.<A, C, B>map1_(f));
682      }
683    
684      /**
685       * Promotes this function to map over the second element of a pair.
686       *
687       * @return This function promoted to map over the second element of a pair.
688       */
689      public <C> FW<P2<C, A>, P2<C, B>> mapSnd() {
690        return $(P2.<C, A, B>map2_(f));
691      }
692    
693      /**
694       * Promotes this function to map over both elements of a pair.
695       *
696       * @return This function promoted to map over both elements of a pair.
697       */
698      public FW<P2<A, A>, P2<B, B>> mapBoth() {
699        return $(new F<P2<A, A>, P2<B, B>>() {
700          public P2<B, B> f(final P2<A, A> aap2) {
701            return P2.map(FW.this, aap2);
702          }
703        });
704      }
705    
706      /**
707       * Maps this function over a SynchronousQueue.
708       *
709       * @param as A SynchronousQueue to map this function over.
710       * @return A new SynchronousQueue with this function applied to each element.
711       */
712      public SynchronousQueue<B> map(final SynchronousQueue<A> as) {
713        final SynchronousQueue<B> bs = new SynchronousQueue<B>();
714        bs.addAll(iterableStream(as).map(this).toCollection());
715        return bs;
716      }
717    
718    
719      /**
720       * Maps this function over a PriorityBlockingQueue.
721       *
722       * @param as A PriorityBlockingQueue to map this function over.
723       * @return A new PriorityBlockingQueue with this function applied to each element.
724       */
725      public PriorityBlockingQueue<B> map(final PriorityBlockingQueue<A> as) {
726        return new PriorityBlockingQueue<B>(iterableStream(as).map(this).toCollection());
727      }
728    
729      /**
730       * Maps this function over a LinkedBlockingQueue.
731       *
732       * @param as A LinkedBlockingQueue to map this function over.
733       * @return A new LinkedBlockingQueue with this function applied to each element.
734       */
735      public LinkedBlockingQueue<B> map(final LinkedBlockingQueue<A> as) {
736        return new LinkedBlockingQueue<B>(iterableStream(as).map(this).toCollection());
737      }
738    
739      /**
740       * Maps this function over a CopyOnWriteArraySet.
741       *
742       * @param as A CopyOnWriteArraySet to map this function over.
743       * @return A new CopyOnWriteArraySet with this function applied to each element.
744       */
745      public CopyOnWriteArraySet<B> map(final CopyOnWriteArraySet<A> as) {
746        return new CopyOnWriteArraySet<B>(iterableStream(as).map(this).toCollection());
747      }
748    
749      /**
750       * Maps this function over a CopyOnWriteArrayList.
751       *
752       * @param as A CopyOnWriteArrayList to map this function over.
753       * @return A new CopyOnWriteArrayList with this function applied to each element.
754       */
755      public CopyOnWriteArrayList<B> map(final CopyOnWriteArrayList<A> as) {
756        return new CopyOnWriteArrayList<B>(iterableStream(as).map(this).toCollection());
757      }
758    
759      /**
760       * Maps this function over a ConcurrentLinkedQueue.
761       *
762       * @param as A ConcurrentLinkedQueue to map this function over.
763       * @return A new ConcurrentLinkedQueue with this function applied to each element.
764       */
765      public ConcurrentLinkedQueue<B> map(final ConcurrentLinkedQueue<A> as) {
766        return new ConcurrentLinkedQueue<B>(iterableStream(as).map(this).toCollection());
767      }
768    
769      /**
770       * Maps this function over an ArrayBlockingQueue.
771       *
772       * @param as An ArrayBlockingQueue to map this function over.
773       * @return A new ArrayBlockingQueue with this function applied to each element.
774       */
775      public ArrayBlockingQueue<B> map(final ArrayBlockingQueue<A> as) {
776        final ArrayBlockingQueue<B> bs = new ArrayBlockingQueue<B>(as.size());
777        bs.addAll(iterableStream(as).map(this).toCollection());
778        return bs;
779      }
780    
781    
782      /**
783       * Maps this function over a TreeSet.
784       *
785       * @param as A TreeSet to map this function over.
786       * @return A new TreeSet with this function applied to each element.
787       */
788      public TreeSet<B> map(final TreeSet<A> as) {
789        return new TreeSet<B>(iterableStream(as).map(this).toCollection());
790      }
791    
792      /**
793       * Maps this function over a PriorityQueue.
794       *
795       * @param as A PriorityQueue to map this function over.
796       * @return A new PriorityQueue with this function applied to each element.
797       */
798      public PriorityQueue<B> map(final PriorityQueue<A> as) {
799        return new PriorityQueue<B>(iterableStream(as).map(this).toCollection());
800      }
801    
802      /**
803       * Maps this function over a LinkedList.
804       *
805       * @param as A LinkedList to map this function over.
806       * @return A new LinkedList with this function applied to each element.
807       */
808      public LinkedList<B> map(final LinkedList<A> as) {
809        return new LinkedList<B>(iterableStream(as).map(this).toCollection());
810      }
811    
812      /**
813       * Maps this function over an ArrayList.
814       *
815       * @param as An ArrayList to map this function over.
816       * @return A new ArrayList with this function applied to each element.
817       */
818      public ArrayList<B> map(final ArrayList<A> as) {
819        return new ArrayList<B>(iterableStream(as).map(this).toCollection());
820      }
821    }