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