/
Variant.java
93 lines (82 loc) · 2.45 KB
/
Variant.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package fj.test;
import fj.F;
import static fj.test.Gen.gen;
import java.util.HashMap;
/**
* A memoised generator variant. Stores generators that have already been computed for the given arguments.
*
* @version %build.number%
*/
public final class Variant {
private static final HashMap<LongGen, Gen<?>> variantMemo = new HashMap<LongGen, Gen<?>>();
private static final class LongGen {
private final long n;
private final Gen<?> gen;
LongGen(final long n, final Gen<?> gen) {
this.n = n;
this.gen = gen;
}
public boolean equals(final Object o) {
return o != null &&
o.getClass() == LongGen.class &&
n == ((LongGen)o).n &&
gen == ((LongGen)o).gen;
}
public int hashCode() {
final int p = 419;
int result = 239;
result = p * result + (int) (n ^ n >>> 32);
result = p * result + gen.hashCode();
return result;
}
}
private Variant() {
throw new UnsupportedOperationException();
}
/**
* Produces a generator that is independent of the given generator using the given value.
*
* @param n The value to produce the new generator from.
* @param g The generator to produce the new generator from.
* @return A generator that is independent of the given generator using the given value.
*/
public static <A> Gen<A> variant(final long n, final Gen<A> g) {
final LongGen p = new LongGen(n, g);
final Gen<?> gx = variantMemo.get(p);
if(gx == null) {
final Gen<A> t = gen(new F<Integer, F<Rand, A>>() {
public F<Rand, A> f(final Integer i) {
return new F<Rand, A>() {
public A f(final Rand r) {
return g.gen(i, r.reseed(n));
}
};
}
});
variantMemo.put(p, t);
return t;
} else return gen(new F<Integer, F<Rand, A>>() {
public F<Rand, A> f(final Integer i) {
return new F<Rand, A>() {
@SuppressWarnings({"unchecked"})
public A f(final Rand r) {
return (A)gx.gen(i, r);
}
};
}
});
}
/**
* A curried version of {@link #variant(long, Gen)}.
*
* @param n The value to produce the new generator from.
* @return A curried version of {@link #variant(long, Gen)}.
*/
public static <A> F<Gen<A>, Gen<A>> variant(final long n) {
return new F<Gen<A>, Gen<A>>() {
public Gen<A> f(final Gen<A> g) {
return variant(n, g);
}
};
}
}