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 }