001 package fj.pre; 002 003 import fj.F; 004 import static fj.Function.compose; 005 import fj.P1; 006 import fj.P2; 007 import fj.P3; 008 import fj.P4; 009 import fj.P5; 010 import fj.P6; 011 import fj.P7; 012 import fj.P8; 013 import fj.data.Array; 014 import fj.data.Either; 015 import fj.data.List; 016 import fj.data.NonEmptyList; 017 import fj.data.Option; 018 import fj.data.Stream; 019 import fj.data.Tree; 020 import fj.data.Validation; 021 import fj.data.vector.V2; 022 import fj.data.vector.V3; 023 import fj.data.vector.V4; 024 import fj.data.vector.V5; 025 import fj.data.vector.V6; 026 import fj.data.vector.V7; 027 import fj.data.vector.V8; 028 029 /** 030 * Produces a hash code for an object which should attempt uniqueness. 031 * 032 * @version %build.number%<br> 033 * <ul> 034 * <li>$LastChangedRevision: 122 $</li> 035 * <li>$LastChangedDate: 2009-04-25 08:24:38 +1000 (Sat, 25 Apr 2009) $</li> 036 * </ul> 037 */ 038 public final class Hash<A> { 039 private final F<A, Integer> f; 040 041 private Hash(final F<A, Integer> f) { 042 this.f = f; 043 } 044 045 /** 046 * Compute the hash of the given value. 047 * 048 * @param a The value to compute the hash value for. 049 * @return The hash value. 050 */ 051 public int hash(final A a) { 052 return f.f(a); 053 } 054 055 /** 056 * Maps the given function across this hash as a contra-variant functor. 057 * 058 * @param g The function to map. 059 * @return A new hash. 060 */ 061 public <B> Hash<B> comap(final F<B, A> g) { 062 return new Hash<B>(compose(f, g)); 063 } 064 065 /** 066 * Construct a hash with the given hash function. 067 * 068 * @param f The function to construct the hash with. 069 * @return A hash that uses the given function. 070 */ 071 public static <A> Hash<A> hash(final F<A, Integer> f) { 072 return new Hash<A>(f); 073 } 074 075 /** 076 * A hash that uses {@link Object#hashCode()}. 077 * 078 * @return A hash that uses {@link Object#hashCode()}. 079 */ 080 public static <A> Hash<A> anyHash() { 081 return new Hash<A>(new F<A, Integer>() { 082 public Integer f(final A a) { 083 return a.hashCode(); 084 } 085 }); 086 } 087 088 /** 089 * A hash instance for the <code>boolean</code> type. 090 */ 091 public static final Hash<Boolean> booleanHash = anyHash(); 092 093 /** 094 * A hash instance for the <code>byte</code> type. 095 */ 096 public static final Hash<Byte> byteHash = anyHash(); 097 098 /** 099 * A hash instance for the <code>char</code> type. 100 */ 101 public static final Hash<Character> charHash = anyHash(); 102 103 /** 104 * A hash instance for the <code>double</code> type. 105 */ 106 public static final Hash<Double> doubleHash = anyHash(); 107 108 /** 109 * A hash instance for the <code>float</code> type. 110 */ 111 public static final Hash<Float> floatHash = anyHash(); 112 113 /** 114 * A hash instance for the <code>int</code> type. 115 */ 116 public static final Hash<Integer> intHash = anyHash(); 117 118 /** 119 * A hash instance for the <code>long</code> type. 120 */ 121 public static final Hash<Long> longHash = anyHash(); 122 123 /** 124 * A hash instance for the <code>short</code> type. 125 */ 126 public static final Hash<Short> shortHash = anyHash(); 127 128 /** 129 * A hash instance for the <code>String</code> type. 130 */ 131 public static final Hash<String> stringHash = anyHash(); 132 133 /** 134 * A hash instance for the {@link StringBuffer} type. 135 */ 136 public static final Hash<StringBuffer> stringBufferHash = new Hash<StringBuffer>(new F<StringBuffer, Integer>() { 137 public Integer f(final StringBuffer sb) { 138 final int p = 419; 139 int r = 239; 140 141 for (int i = 0; i < sb.length(); i++) 142 r = p * r + sb.charAt(i); 143 144 return r; 145 } 146 }); 147 148 /** 149 * A hash instance for the {@link StringBuilder} type. 150 */ 151 public static final Hash<StringBuilder> stringBuilderHash = new Hash<StringBuilder>(new F<StringBuilder, Integer>() { 152 public Integer f(final StringBuilder sb) { 153 final int p = 419; 154 int r = 239; 155 156 for (int i = 0; i < sb.length(); i++) 157 r = p * r + sb.charAt(i); 158 159 return r; 160 } 161 }); 162 163 /** 164 * A hash instance for the {@link Either} type. 165 * 166 * @param ha Hash the left side of <code>Either</code>. 167 * @param hb Hash the right side of <code>Either</code>. 168 * @return A hash instance for the {@link Either} type. 169 */ 170 public static <A, B> Hash<Either<A, B>> eitherHash(final Hash<A> ha, final Hash<B> hb) { 171 return new Hash<Either<A, B>>(new F<Either<A, B>, Integer>() { 172 public Integer f(final Either<A, B> e) { 173 return e.isLeft() ? ha.hash(e.left().value()) : hb.hash(e.right().value()); 174 } 175 }); 176 } 177 178 /** 179 * A hash instance for the {@link Validation} type. 180 * 181 * @param ha Hash the failing side of <code>Validation</code>. 182 * @param hb Hash the succeeding side of <code>Validation</code>. 183 * @return A hash instance for the {@link Validation} type. 184 */ 185 public static <A, B> Hash<Validation<A, B>> validationHash(final Hash<A> ha, final Hash<B> hb) { 186 return eitherHash(ha, hb).comap(Validation.<A, B>either()); 187 } 188 189 /** 190 * A hash instance for the {@link List} type. 191 * 192 * @param ha A hash for the elements of the list. 193 * @return A hash instance for the {@link List} type. 194 */ 195 public static <A> Hash<List<A>> listHash(final Hash<A> ha) { 196 return new Hash<List<A>>(new F<List<A>, Integer>() { 197 public Integer f(final List<A> as) { 198 final int p = 419; 199 int r = 239; 200 List<A> aas = as; 201 202 while (!aas.isEmpty()) { 203 r = p * r + ha.hash(aas.head()); 204 aas = aas.tail(); 205 } 206 207 return r; 208 } 209 }); 210 } 211 212 /** 213 * A hash instance for the {@link NonEmptyList} type. 214 * 215 * @param ha A hash for the elements of the non-empty list. 216 * @return A hash instance for the {@link NonEmptyList} type. 217 */ 218 public static <A> Hash<NonEmptyList<A>> nonEmptyListHash(final Hash<A> ha) { 219 return listHash(ha).comap(NonEmptyList.<A>toList_()); 220 } 221 222 /** 223 * A hash instance for the {@link Option} type. 224 * 225 * @param ha A hash for the element of the optional value. 226 * @return A hash instance for the {@link Option} type. 227 */ 228 public static <A> Hash<Option<A>> optionHash(final Hash<A> ha) { 229 return new Hash<Option<A>>(new F<Option<A>, Integer>() { 230 public Integer f(final Option<A> o) { 231 return o.isNone() ? 0 : ha.hash(o.some()); 232 } 233 }); 234 } 235 236 /** 237 * A hash instance for the {@link Stream} type. 238 * 239 * @param ha A hash for the elements of the stream. 240 * @return A hash instance for the {@link Stream} type. 241 */ 242 public static <A> Hash<Stream<A>> streamHash(final Hash<A> ha) { 243 return new Hash<Stream<A>>(new F<Stream<A>, Integer>() { 244 public Integer f(final Stream<A> as) { 245 final int p = 419; 246 int r = 239; 247 Stream<A> aas = as; 248 249 while (!aas.isEmpty()) { 250 r = p * r + ha.hash(aas.head()); 251 aas = aas.tail()._1(); 252 } 253 254 return r; 255 } 256 }); 257 } 258 259 /** 260 * A hash instance for the {@link Array} type. 261 * 262 * @param ha A hash for the elements of the array. 263 * @return A hash instance for the {@link Array} type. 264 */ 265 public static <A> Hash<Array<A>> arrayHash(final Hash<A> ha) { 266 return new Hash<Array<A>>(new F<Array<A>, Integer>() { 267 public Integer f(final Array<A> as) { 268 final int p = 419; 269 int r = 239; 270 271 for (int i = 0; i < as.length(); i++) { 272 r = p * r + ha.hash(as.get(i)); 273 } 274 275 return r; 276 } 277 }); 278 } 279 280 /** 281 * A hash instance for the {@link Tree} type. 282 * 283 * @param ha A hash for the elements of the tree. 284 * @return A hash instance for the {@link Tree} type. 285 */ 286 public static <A> Hash<Tree<A>> treeHash(final Hash<A> ha) { 287 return streamHash(ha).comap(Tree.<A>flatten_()); 288 } 289 290 /** 291 * A hash instance for a product-1. 292 * 293 * @param ha A hash for the first element of the product. 294 * @return A hash instance for a product-1. 295 */ 296 public static <A> Hash<P1<A>> p1Hash(final Hash<A> ha) { 297 return ha.comap(P1.<A>__1()); 298 } 299 300 /** 301 * A hash instance for a product-2. 302 * 303 * @param ha A hash for the first element of the product. 304 * @param hb A hash for the second element of the product. 305 * @return A hash instance for a product-2. 306 */ 307 public static <A, B> Hash<P2<A, B>> p2Hash(final Hash<A> ha, final Hash<B> hb) { 308 return new Hash<P2<A, B>>(new F<P2<A, B>, Integer>() { 309 public Integer f(final P2<A, B> p2) { 310 final int p = 419; 311 int r = 239; 312 313 r = p * r + ha.hash(p2._1()); 314 r = p * r + hb.hash(p2._2()); 315 316 return r; 317 } 318 }); 319 } 320 321 /** 322 * A hash instance for a product-3. 323 * 324 * @param ha A hash for the first element of the product. 325 * @param hb A hash for the second element of the product. 326 * @param hc A hash for the third element of the product. 327 * @return A hash instance for a product-3. 328 */ 329 public static <A, B, C> Hash<P3<A, B, C>> p3Hash(final Hash<A> ha, final Hash<B> hb, final Hash<C> hc) { 330 return new Hash<P3<A, B, C>>(new F<P3<A, B, C>, Integer>() { 331 public Integer f(final P3<A, B, C> p3) { 332 final int p = 419; 333 int r = 239; 334 335 r = p * r + ha.hash(p3._1()); 336 r = p * r + hb.hash(p3._2()); 337 r = p * r + hc.hash(p3._3()); 338 339 return r; 340 } 341 }); 342 } 343 344 /** 345 * A hash instance for a product-4. 346 * 347 * @param ha A hash for the first element of the product. 348 * @param hb A hash for the second element of the product. 349 * @param hc A hash for the third element of the product. 350 * @param hd A hash for the fourth element of the product. 351 * @return A hash instance for a product-4. 352 */ 353 public static <A, B, C, D> Hash<P4<A, B, C, D>> p4Hash(final Hash<A> ha, final Hash<B> hb, final Hash<C> hc, 354 final Hash<D> hd) { 355 return new Hash<P4<A, B, C, D>>(new F<P4<A, B, C, D>, Integer>() { 356 public Integer f(final P4<A, B, C, D> p4) { 357 final int p = 419; 358 int r = 239; 359 360 r = p * r + ha.hash(p4._1()); 361 r = p * r + hb.hash(p4._2()); 362 r = p * r + hc.hash(p4._3()); 363 r = p * r + hd.hash(p4._4()); 364 365 return r; 366 } 367 }); 368 } 369 370 /** 371 * A hash instance for a product-5. 372 * 373 * @param ha A hash for the first element of the product. 374 * @param hb A hash for the second element of the product. 375 * @param hc A hash for the third element of the product. 376 * @param hd A hash for the fourth element of the product. 377 * @param he A hash for the fifth element of the product. 378 * @return A hash instance for a product-5. 379 */ 380 public static <A, B, C, D, E> Hash<P5<A, B, C, D, E>> p5Hash(final Hash<A> ha, final Hash<B> hb, final Hash<C> hc, 381 final Hash<D> hd, final Hash<E> he) { 382 return new Hash<P5<A, B, C, D, E>>(new F<P5<A, B, C, D, E>, Integer>() { 383 public Integer f(final P5<A, B, C, D, E> p5) { 384 final int p = 419; 385 int r = 239; 386 387 r = p * r + ha.hash(p5._1()); 388 r = p * r + hb.hash(p5._2()); 389 r = p * r + hc.hash(p5._3()); 390 r = p * r + hd.hash(p5._4()); 391 r = p * r + he.hash(p5._5()); 392 393 return r; 394 } 395 }); 396 } 397 398 /** 399 * A hash instance for a product-6. 400 * 401 * @param ha A hash for the first element of the product. 402 * @param hb A hash for the second element of the product. 403 * @param hc A hash for the third element of the product. 404 * @param hd A hash for the fourth element of the product. 405 * @param he A hash for the fifth element of the product. 406 * @param hf A hash for the sixth element of the product. 407 * @return A hash instance for a product-6. 408 */ 409 public static <A, B, C, D, E, F$> Hash<P6<A, B, C, D, E, F$>> p6Hash(final Hash<A> ha, final Hash<B> hb, 410 final Hash<C> hc, final Hash<D> hd, 411 final Hash<E> he, final Hash<F$> hf) { 412 return new Hash<P6<A, B, C, D, E, F$>>(new F<P6<A, B, C, D, E, F$>, Integer>() { 413 public Integer f(final P6<A, B, C, D, E, F$> p6) { 414 final int p = 419; 415 int r = 239; 416 417 r = p * r + ha.hash(p6._1()); 418 r = p * r + hb.hash(p6._2()); 419 r = p * r + hc.hash(p6._3()); 420 r = p * r + hd.hash(p6._4()); 421 r = p * r + he.hash(p6._5()); 422 r = p * r + hf.hash(p6._6()); 423 424 return r; 425 } 426 }); 427 } 428 429 /** 430 * A hash instance for a product-7. 431 * 432 * @param ha A hash for the first element of the product. 433 * @param hb A hash for the second element of the product. 434 * @param hc A hash for the third element of the product. 435 * @param hd A hash for the fourth element of the product. 436 * @param he A hash for the fifth element of the product. 437 * @param hf A hash for the sixth element of the product. 438 * @param hg A hash for the seventh element of the product. 439 * @return A hash instance for a product-7. 440 */ 441 public static <A, B, C, D, E, F$, G> Hash<P7<A, B, C, D, E, F$, G>> p7Hash(final Hash<A> ha, final Hash<B> hb, 442 final Hash<C> hc, final Hash<D> hd, 443 final Hash<E> he, final Hash<F$> hf, 444 final Hash<G> hg) { 445 return new Hash<P7<A, B, C, D, E, F$, G>>(new F<P7<A, B, C, D, E, F$, G>, Integer>() { 446 public Integer f(final P7<A, B, C, D, E, F$, G> p7) { 447 final int p = 419; 448 int r = 239; 449 450 r = p * r + ha.hash(p7._1()); 451 r = p * r + hb.hash(p7._2()); 452 r = p * r + hc.hash(p7._3()); 453 r = p * r + hd.hash(p7._4()); 454 r = p * r + he.hash(p7._5()); 455 r = p * r + hf.hash(p7._6()); 456 r = p * r + hg.hash(p7._7()); 457 458 return r; 459 } 460 }); 461 } 462 463 /** 464 * A hash instance for a product-8. 465 * 466 * @param ha A hash for the first element of the product. 467 * @param hb A hash for the second element of the product. 468 * @param hc A hash for the third element of the product. 469 * @param hd A hash for the fourth element of the product. 470 * @param he A hash for the fifth element of the product. 471 * @param hf A hash for the sixth element of the product. 472 * @param hg A hash for the seventh element of the product. 473 * @param hh A hash for the eighth element of the product. 474 * @return A hash instance for a product-8. 475 */ 476 public static <A, B, C, D, E, F$, G, H> Hash<P8<A, B, C, D, E, F$, G, H>> p8Hash(final Hash<A> ha, final Hash<B> hb, 477 final Hash<C> hc, final Hash<D> hd, 478 final Hash<E> he, final Hash<F$> hf, 479 final Hash<G> hg, final Hash<H> hh) { 480 return new Hash<P8<A, B, C, D, E, F$, G, H>>(new F<P8<A, B, C, D, E, F$, G, H>, Integer>() { 481 public Integer f(final P8<A, B, C, D, E, F$, G, H> p8) { 482 final int p = 419; 483 int r = 239; 484 485 r = p * r + ha.hash(p8._1()); 486 r = p * r + hb.hash(p8._2()); 487 r = p * r + hc.hash(p8._3()); 488 r = p * r + hd.hash(p8._4()); 489 r = p * r + he.hash(p8._5()); 490 r = p * r + hf.hash(p8._6()); 491 r = p * r + hg.hash(p8._7()); 492 r = p * r + hh.hash(p8._8()); 493 494 return r; 495 } 496 }); 497 } 498 499 /** 500 * A hash instance for a vector-2. 501 * 502 * @param ea A hash for the elements of the vector. 503 * @return A hash instance for a vector-2. 504 */ 505 public static <A> Hash<V2<A>> v2Hash(final Hash<A> ea) { 506 return streamHash(ea).comap(V2.<A>toStream_()); 507 } 508 509 /** 510 * A hash instance for a vector-3. 511 * 512 * @param ea A hash for the elements of the vector. 513 * @return A hash instance for a vector-3. 514 */ 515 public static <A> Hash<V3<A>> v3Hash(final Hash<A> ea) { 516 return streamHash(ea).comap(V3.<A>toStream_()); 517 } 518 519 /** 520 * A hash instance for a vector-4. 521 * 522 * @param ea A hash for the elements of the vector. 523 * @return A hash instance for a vector-4. 524 */ 525 public static <A> Hash<V4<A>> v4Hash(final Hash<A> ea) { 526 return streamHash(ea).comap(V4.<A>toStream_()); 527 } 528 529 /** 530 * A hash instance for a vector-5. 531 * 532 * @param ea A hash for the elements of the vector. 533 * @return A hash instance for a vector-5. 534 */ 535 public static <A> Hash<V5<A>> v5Hash(final Hash<A> ea) { 536 return streamHash(ea).comap(V5.<A>toStream_()); 537 } 538 539 /** 540 * A hash instance for a vector-6. 541 * 542 * @param ea A hash for the elements of the vector. 543 * @return A hash instance for a vector-6. 544 */ 545 public static <A> Hash<V6<A>> v6Hash(final Hash<A> ea) { 546 return streamHash(ea).comap(V6.<A>toStream_()); 547 } 548 549 /** 550 * A hash instance for a vector-7. 551 * 552 * @param ea A hash for the elements of the vector. 553 * @return A hash instance for a vector-7. 554 */ 555 public static <A> Hash<V7<A>> v7Hash(final Hash<A> ea) { 556 return streamHash(ea).comap(V7.<A>toStream_()); 557 } 558 559 /** 560 * A hash instance for a vector-8. 561 * 562 * @param ea A hash for the elements of the vector. 563 * @return A hash instance for a vector-8. 564 */ 565 public static <A> Hash<V8<A>> v8Hash(final Hash<A> ea) { 566 return streamHash(ea).comap(V8.<A>toStream_()); 567 } 568 }