001    package fj.data.vector;
002    
003    import fj.F;
004    import fj.F2;
005    import fj.P1;
006    import fj.P2;
007    import fj.P5;
008    import fj.P6;
009    import static fj.Function.curry;
010    import static fj.P.p2;
011    import fj.data.Array;
012    import fj.data.NonEmptyList;
013    import fj.data.Stream;
014    
015    import java.util.Iterator;
016    
017    /**
018     * A vector-6.
019     */
020    public final class V6<A> implements Iterable<A> {
021    
022      private final V5<A> tail;
023      private final P1<A> head;
024    
025      private V6(final P1<A> head, final V5<A> tail) {
026        this.head = head;
027        this.tail = tail;
028      }
029    
030      /**
031       * Creates a vector-6 from a homogeneous product-6.
032       *
033       * @param p The product-6 from which to create a vector.
034       * @return A new vector-6.
035       */
036      public static <A> V6<A> p(final P6<A, A, A, A, A, A> p) {
037        return new V6<A>(new P1<A>() {
038          public A _1() {
039            return p._1();
040          }
041        }, V5.p(new P5<A, A, A, A, A>() {
042          public A _1() {
043            return p._2();
044          }
045    
046          public A _2() {
047            return p._3();
048          }
049    
050          public A _3() {
051            return p._4();
052          }
053    
054          public A _4() {
055            return p._5();
056          }
057    
058          public A _5() {
059            return p._6();
060          }
061        }));
062      }
063    
064      /**
065       * Creates a vector-6 from a head and a tail.
066       *
067       * @param head The value to put as the first element of the vector.
068       * @param tail The vector representing all but the first element of the new vector.
069       * @return The new vector.
070       */
071      public static <A> V6<A> cons(final P1<A> head, final V5<A> tail) {
072        return new V6<A>(head, tail);
073      }
074    
075      /**
076       * Returns the first element of this vector.
077       *
078       * @return the first element of this vector.
079       */
080      public A _1() {
081        return head._1();
082      }
083    
084      /**
085       * Returns the second element of this vector.
086       *
087       * @return the second element of this vector.
088       */
089      public A _2() {
090        return tail._1();
091      }
092    
093      /**
094       * Returns the third element of this vector.
095       *
096       * @return the third element of this vector.
097       */
098      public A _3() {
099        return tail._2();
100      }
101    
102      /**
103       * Returns the fourth element of this vector.
104       *
105       * @return the fourth element of this vector.
106       */
107      public A _4() {
108        return tail._3();
109      }
110    
111      /**
112       * Returns the fifth element of this vector.
113       *
114       * @return the fifth element of this vector.
115       */
116      public A _5() {
117        return tail._4();
118      }
119    
120      /**
121       * Returns the sixth element of this vector.
122       *
123       * @return the sixth element of this vector.
124       */
125      public A _6() {
126        return tail._5();
127      }
128    
129      /**
130       * Returns all but the first element of this vector, as a vector-5.
131       *
132       * @return all but the first element of this vector, as a vector-5.
133       */
134      public V5<A> tail() {
135        return tail;
136      }
137    
138      /**
139       * Returns the first element of this vector, as a product-1.
140       *
141       * @return the first element of this vector, as a product-1.
142       */
143      public P1<A> head() {
144        return head;
145      }
146    
147      /**
148       * Returns an iterator for the elements of this vector.
149       *
150       * @return an iterator for the elements of this vector.
151       */
152      public Iterator<A> iterator() {
153        return toStream().iterator();
154      }
155    
156      /**
157       * Returns a homogeneous product-6 equivalent to this vector.
158       *
159       * @return a homogeneous product-6 equivalent to this vector.
160       */
161      public P6<A, A, A, A, A, A> p() {
162        return new P6<A, A, A, A, A, A>() {
163          public A _1() {
164            return V6.this._1();
165          }
166    
167          public A _2() {
168            return V6.this._2();
169          }
170    
171          public A _3() {
172            return V6.this._3();
173          }
174    
175          public A _4() {
176            return V6.this._4();
177          }
178    
179          public A _5() {
180            return V6.this._5();
181          }
182    
183          public A _6() {
184            return V6.this._6();
185          }
186        };
187      }
188    
189      /**
190       * Returns a nonempty list with the elements of this vector.
191       *
192       * @return a nonempty list with the elements of this vector.
193       */
194      public NonEmptyList<A> toNonEmptyList() {
195        return NonEmptyList.nel(_1(), tail.toNonEmptyList().toList());
196      }
197    
198      /**
199       * Returns a stream of the elements of this vector.
200       *
201       * @return a stream of the elements of this vector.
202       */
203      public Stream<A> toStream() {
204        return Stream.cons(head._1(), new P1<Stream<A>>() {
205          public Stream<A> _1() {
206            return tail.toStream();
207          }
208        });
209      }
210    
211      /**
212       * Returns an array with the elements of this vector.
213       *
214       * @return an array with the elements of this vector.
215       */
216      @SuppressWarnings("unchecked")
217      public Array<A> toArray() {
218        return Array.array(_1(), _2(), _3(), _4(), _5(), _6());
219      }
220    
221      /**
222       * Maps the given function across this vector.
223       *
224       * @param f The function to map across this vector.
225       * @return A new vector after the given function has been applied to each element.
226       */
227      public <B> V6<B> map(final F<A, B> f) {
228        return new V6<B>(head.map(f), tail.map(f));
229      }
230    
231      /**
232       * Performs function application within a vector (applicative functor pattern).
233       *
234       * @param vf The vector of functions to apply.
235       * @return A new vector after zipping the given vector of functions over this vector.
236       */
237      public <B> V6<B> apply(final V6<F<A, B>> vf) {
238        return new V6<B>(P1.<A, B>apply(head, vf.head()), tail.apply(vf.tail()));
239      }
240    
241      /**
242       * Zips this vector with the given vector using the given function to produce a new vector.
243       *
244       * @param bs The vector to zip this vector with.
245       * @param f  The function to zip this vector and the given vector with.
246       * @return A new vector with the results of the function.
247       */
248      public <B, C> V6<C> zipWith(final F<A, F<B, C>> f, final V6<B> bs) {
249        return bs.apply(map(f));
250      }
251    
252      /**
253       * Zips this vector with the given vector to produce a vector of pairs.
254       *
255       * @param bs The vector to zip this vector with.
256       * @return A new vector with a length the same as the shortest of this vector and the given
257       *         vector.
258       */
259      public <B> V6<P2<A, B>> zip(final V6<B> bs) {
260        final F<A, F<B, P2<A, B>>> __2 = p2();
261        return zipWith(__2, bs);
262      }
263    
264      /**
265       * Zips this vector with the given vector to produce a vector of vectors.
266       *
267       * @param bs The vector to zip this vector with.
268       * @return A new vector of vectors.
269       */
270      public V6<V2<A>> vzip(final V6<A> bs) {
271        final F2<A, A, V2<A>> __2 = V.v2();
272        return zipWith(curry(__2), bs);
273      }
274    
275      /**
276       * Returns a function that transforms a vector-6 to a stream of its elements.
277       *
278       * @return a function that transforms a vector-6 to a stream of its elements.
279       */
280      public static <A> F<V6<A>, Stream<A>> toStream_() {
281        return new F<V6<A>, Stream<A>>() {
282          public Stream<A> f(final V6<A> v) {
283            return v.toStream();
284          }
285        };
286      }
287    
288      /**
289       * Returns a function that transforms a vector-6 to the equivalent product-6.
290       *
291       * @return a function that transforms a vector-6 to the equivalent product-6.
292       */
293      public static <A> F<V6<A>, P6<A, A, A, A, A, A>> p_() {
294        return new F<V6<A>, P6<A, A, A, A, A, A>>() {
295          public P6<A, A, A, A, A, A> f(final V6<A> v) {
296            return v.p();
297          }
298        };
299      }
300    
301      /**
302       * A first-class function to get the first element of a vector.
303       *
304       * @return a function that gets the first element of a given vector.
305       */
306      public static <A> F<V6<A>, A> __1() {
307        return new F<V6<A>, A>() {
308          public A f(final V6<A> v) {
309            return v._1();
310          }
311        };
312      }
313    
314      /**
315       * A first-class function to get the second element of a vector.
316       *
317       * @return a function that gets the second element of a given vector.
318       */
319      public static <A> F<V6<A>, A> __2() {
320        return new F<V6<A>, A>() {
321          public A f(final V6<A> v) {
322            return v._2();
323          }
324        };
325      }
326    
327      /**
328       * A first-class function to get the third element of a vector.
329       *
330       * @return a function that gets the third element of a given vector.
331       */
332      public static <A> F<V6<A>, A> __3() {
333        return new F<V6<A>, A>() {
334          public A f(final V6<A> v) {
335            return v._3();
336          }
337        };
338      }
339    
340      /**
341       * A first-class function to get the third element of a vector.
342       *
343       * @return a function that gets the third element of a given vector.
344       */
345      public static <A> F<V6<A>, A> __4() {
346        return new F<V6<A>, A>() {
347          public A f(final V6<A> v) {
348            return v._4();
349          }
350        };
351      }
352    
353      /**
354       * A first-class function to get the third element of a vector.
355       *
356       * @return a function that gets the third element of a given vector.
357       */
358      public static <A> F<V6<A>, A> __5() {
359        return new F<V6<A>, A>() {
360          public A f(final V6<A> v) {
361            return v._5();
362          }
363        };
364      }
365    
366      /**
367       * A first-class function to get the third element of a vector.
368       *
369       * @return a function that gets the third element of a given vector.
370       */
371      public static <A> F<V6<A>, A> __6() {
372        return new F<V6<A>, A>() {
373          public A f(final V6<A> v) {
374            return v._6();
375          }
376        };
377      }
378    
379    }