diff src/main/java/fj/test/Variant.java @ 0:fe80c1edf1be

add getLoop
author tatsuki
date Fri, 20 Mar 2015 21:04:03 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/fj/test/Variant.java	Fri Mar 20 21:04:03 2015 +0900
@@ -0,0 +1,93 @@
+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);
+      }
+    };
+  }
+}
+