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