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.P3; 008 import static fj.Function.curry; 009 import static fj.P.p2; 010 import fj.data.Array; 011 import fj.data.NonEmptyList; 012 import fj.data.Stream; 013 014 import java.util.Iterator; 015 016 /** 017 * A vector-3. 018 */ 019 public final class V3<A> implements Iterable<A> { 020 021 private final V2<A> tail; 022 private final P1<A> head; 023 024 private V3(final P1<A> head, final V2<A> tail) { 025 this.head = head; 026 this.tail = tail; 027 } 028 029 /** 030 * Creates a vector-3 from a homogeneous product-3. 031 * 032 * @param p The product-3 from which to create a vector. 033 * @return A new vector-3. 034 */ 035 public static <A> V3<A> p(final P3<A, A, A> p) { 036 return new V3<A>(new P1<A>() { 037 public A _1() { 038 return p._1(); 039 } 040 }, V2.p(new P2<A, A>() { 041 public A _1() { 042 return p._2(); 043 } 044 045 public A _2() { 046 return p._3(); 047 } 048 })); 049 } 050 051 /** 052 * Creates a vector-3 from a head and a tail. 053 * 054 * @param head The value to put as the first element of the vector. 055 * @param tail The vector representing all but the first element of the new vector. 056 * @return The new vector. 057 */ 058 public static <A> V3<A> cons(final P1<A> head, final V2<A> tail) { 059 return new V3<A>(head, tail); 060 } 061 062 /** 063 * Returns the first element of this vector. 064 * 065 * @return the first element of this vector. 066 */ 067 public A _1() { 068 return head._1(); 069 } 070 071 /** 072 * Returns the second element of this vector. 073 * 074 * @return the second element of this vector. 075 */ 076 public A _2() { 077 return tail._1(); 078 } 079 080 /** 081 * Returns the third element of this vector. 082 * 083 * @return the third element of this vector. 084 */ 085 public A _3() { 086 return tail._2(); 087 } 088 089 /** 090 * Returns all but the first element of this vector, as a vector-2. 091 * 092 * @return all but the first element of this vector, as a vector-2. 093 */ 094 public V2<A> tail() { 095 return tail; 096 } 097 098 /** 099 * Returns the first element of this vector, as a product-1. 100 * 101 * @return the first element of this vector, as a product-1. 102 */ 103 public P1<A> head() { 104 return head; 105 } 106 107 /** 108 * Returns a homogeneous product-3 equivalent to this vector. 109 * 110 * @return a homogeneous product-3 equivalent to this vector. 111 */ 112 public P3<A, A, A> p() { 113 return new P3<A, A, A>() { 114 public A _1() { 115 return V3.this._1(); 116 } 117 118 public A _2() { 119 return V3.this._2(); 120 } 121 122 public A _3() { 123 return V3.this._3(); 124 } 125 }; 126 } 127 128 /** 129 * Returns an array with the elements of this vector. 130 * 131 * @return an array with the elements of this vector. 132 */ 133 @SuppressWarnings("unchecked") 134 public Array<A> toArray() { 135 return Array.array(_1(), _2(), _3()); 136 } 137 138 139 /** 140 * Performs function application within a vector (applicative functor pattern). 141 * 142 * @param vf The vector of functions to apply. 143 * @return A new vector after zipping the given vector of functions over this vector. 144 */ 145 public <B> V3<B> apply(final V3<F<A, B>> vf) { 146 return new V3<B>(P1.<A, B>apply(head, vf.head()), tail.apply(vf.tail())); 147 } 148 149 /** 150 * Zips this vector with the given vector using the given function to produce a new vector. 151 * 152 * @param bs The vector to zip this vector with. 153 * @param f The function to zip this vector and the given vector with. 154 * @return A new vector with the results of the function. 155 */ 156 public <B, C> V3<C> zipWith(final F<A, F<B, C>> f, final V3<B> bs) { 157 return bs.apply(map(f)); 158 } 159 160 /** 161 * Zips this vector with the given vector to produce a vector of pairs. 162 * 163 * @param bs The vector to zip this vector with. 164 * @return A new vector with a length the same as the shortest of this vector and the given 165 * vector. 166 */ 167 public <B> V3<P2<A, B>> zip(final V3<B> bs) { 168 final F<A, F<B, P2<A, B>>> __2 = p2(); 169 return zipWith(__2, bs); 170 } 171 172 /** 173 * Zips this vector with the given vector to produce a vector of vectors. 174 * 175 * @param bs The vector to zip this vector with. 176 * @return A new vector of vectors. 177 */ 178 public V3<V2<A>> vzip(final V3<A> bs) { 179 final F2<A, A, V2<A>> __2 = V.v2(); 180 return zipWith(curry(__2), bs); 181 } 182 183 /** 184 * Returns an iterator for the elements of this vector. 185 * 186 * @return an iterator for the elements of this vector. 187 */ 188 public Iterator<A> iterator() { 189 return toStream().iterator(); 190 } 191 192 /** 193 * Returns a nonempty list with the elements of this vector. 194 * 195 * @return a nonempty list with the elements of this vector. 196 */ 197 public NonEmptyList<A> toNonEmptyList() { 198 return NonEmptyList.nel(head()._1(), tail().toNonEmptyList().toList()); 199 } 200 201 /** 202 * Returns a stream of the elements of this vector. 203 * 204 * @return a stream of the elements of this vector. 205 */ 206 public Stream<A> toStream() { 207 return Stream.cons(head()._1(), new P1<Stream<A>>() { 208 public Stream<A> _1() { 209 return tail().toStream(); 210 } 211 }); 212 } 213 214 /** 215 * Maps the given function across this vector. 216 * 217 * @param f The function to map across this vector. 218 * @return A new vector after the given function has been applied to each element. 219 */ 220 public <B> V3<B> map(final F<A, B> f) { 221 return new V3<B>(head().map(f), tail().map(f)); 222 } 223 224 /** 225 * Returns a function that transforms a vector-3 to a stream of its elements. 226 * 227 * @return a function that transforms a vector-3 to a stream of its elements. 228 */ 229 public static <A> F<V3<A>, Stream<A>> toStream_() { 230 return new F<V3<A>, Stream<A>>() { 231 public Stream<A> f(final V3<A> v) { 232 return v.toStream(); 233 } 234 }; 235 } 236 237 /** 238 * Returns a function that transforms a vector-3 to the equivalent product-3. 239 * 240 * @return a function that transforms a vector-3 to the equivalent product-3. 241 */ 242 public static <A> F<V3<A>, P3<A, A, A>> p_() { 243 return new F<V3<A>, P3<A, A, A>>() { 244 public P3<A, A, A> f(final V3<A> v) { 245 return v.p(); 246 } 247 }; 248 } 249 250 /** 251 * A first-class function to get the first element of a vector. 252 * 253 * @return a function that gets the first element of a given vector. 254 */ 255 public static <A> F<V3<A>, A> __1() { 256 return new F<V3<A>, A>() { 257 public A f(final V3<A> v) { 258 return v._1(); 259 } 260 }; 261 } 262 263 /** 264 * A first-class function to get the second element of a vector. 265 * 266 * @return a function that gets the second element of a given vector. 267 */ 268 public static <A> F<V3<A>, A> __2() { 269 return new F<V3<A>, A>() { 270 public A f(final V3<A> v) { 271 return v._2(); 272 } 273 }; 274 } 275 276 /** 277 * A first-class function to get the third element of a vector. 278 * 279 * @return a function that gets the third element of a given vector. 280 */ 281 public static <A> F<V3<A>, A> __3() { 282 return new F<V3<A>, A>() { 283 public A f(final V3<A> v) { 284 return v._3(); 285 } 286 }; 287 } 288 289 }